Smashing Boxes | 06.30.15 | Code

Merging Rails and Ember-CLI – Part II


  • Android
  • iOS
  • Web

Why?

In part 1 of Merging Rails with ember-cli, I talked about techniques that I use to achieve a smooth development experience when combining a Rails API with an Ember CLI-powered front end. I wanted to build a simple app where people could vote for beer by ranking their favorites on a weighted 1 to N scale. However, I was unsure how Ember would handle a major component of the app: drag-n-drop.

In this post, I will go into more detail about how I implemented HTML5 drag-n-drop functionality for updating beer rankings. I will demonstrate how simple it was to build this functionality into my existing, non-dynamic list of beers.


##VS

##Bootstrapping

I love to use twitter bootstrap when I am prototyping a new idea. Just run…

$ bower install --save-dev ember-cli-bootstrap-sass

…then add the following to the top of your root scss stylesheet:

EmberApp/app/styles/app.scss

@import "bootstrap";
@import "bootstrap/theme";

##Drag-N-Drop

We’ve all heard this request before: “I just want to be able to drag this item here and this item there and POOF, the change is made!” Clients LOVE drag-n-drop. It is a feature I have implemented a million times before, but I almost always use some JQuery library that interfaces with a custom-built API for the sole purpose of building that ONE drag-n-drop component. I was seriously scared that drag-n-drop would be really hard to build in pure Ember, but I am pleased to say that I had it up and running in no time!

The first thing I did was hit the docs. I was pleased to see that EmberView supports drag and drop out of the box. This worked out perfectly, since I knew I would need two views in this component: a line item and a slot to drop each line item into. So, I created myself a line-item and an item-slot view with the necessary event dataTransfer data.

I had to comb through the w3c spec a bit, but I was able to come up with some solid documentation on HTML5 drag-n-drop and the data transfer interface.

EmberApp/app/views/line-item.js

import Ember from 'ember';

export default Ember.View.extend({
attributeBindings: ['draggable'],
draggable: 'true',
templateName: 'line-item',
classNames: 'line_item',

dragStart: function(ev){
var dragData = { id: this.content.get('id') };
ev.dataTransfer.setData('application/json', JSON.stringify(dragData));
}
});

EmberApp/app/templates/line-item.hbs

<span class="weight">{{weight}}</span>
<span class="name">{{beer_name}}</span>

EmberApp/app/views/item-slot.js

import Ember from 'ember';

export default Ember.View.extend({
templateName: 'item-slot',

dragOver: function(ev){
ev.preventDefault();
},

drop: function(ev){
var data = JSON.parse(ev.dataTransfer.getData('application/json'));
this.get('controller').send('swap', data.id, this.content.get('id'));
}
});

EmberApp/app/templates/item-slot.hbs

{{view 'line-item' contentBinding='this'}}

Lastly, I updated my ballot template to use these new views.

EmberApp/app/templates/ballot.hbs

{{#each this.model.sorted_line_items}}
<div class="row">
<div class="col-xs-12">{{view 'item-slot' contentBinding='this'}}</div>
</div>
{{/each}}
<div class="row">
<div class="col-xs-12 new_beer">{{#view 'new-beer' contentBinding='this'}}
<input type="text" placeholder="+ ADD BEER" />
{{/view}}</div>
</div>

Then I update my controller to handle swapping of weights between two line items. It’s a little dirty, but it gets the job done:

EmberApp/app/controller/ballot.js

import Ember from 'ember';

export default Ember.Controller.extend({
sortProperties: ['weight'],

actions: {
swap: function(line_item_id_1, line_item_id_2) {
var li1, li1_weight, li2, li2_weight;
li1 = this.model.get('line_items').findBy('id', line_item_id_1);
li2 = this.model.get('line_items').findBy('id', line_item_id_2);
li1_weight = li1.get('weight');
li2_weight = li2.get('weight');
li1.set('weight', li2_weight);
li2.set('weight', li1_weight);
}
}
});

That’s it, drag-n-drop now works! Yet again Ember proves itself to be an amazing framework for building incredibly dynamic single-page apps with great speed.

In Part 3, I will show you how to persist these changes that you make to your backend Rails application!

##Resources
* Ember-CLI Rails Github Repo
* HTML5 Drag and Drop
* Part 1
* Part 3

Cover photo by OUCHcharley

Careers at Smashing Boxes


Open Positions

We don’t just make great products, we help build great companies.


Contact Us

Get exclusive access to Smashing Boxes news, case studies, and events.

Sign up now
close ×

Get exclusive access to Smashing Boxes news, case studies, and events. Sign up now!

* indicates required