HEY! I'm working on an awesome course on Golang and Ember.js skills that's live soon. Get early access to it here:

nerdyworm

Ember.js Drag and Drop Sorting With jQuery Sortable

Source Code

Drag and drop with ember.js and jQuery sortable is actually pretty easy. However there are a few tricks that I would like to share.

View and Template

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
App.IndexView = Ember.View.extend({
  didInsertElement: function() {
    var controller = this.get('controller');
    this.$(".sortable").sortable({
      update: function(event, ui) {
        var indexes = {};

        $(this).find('.item').each(function(index) {
          indexes[$(this).data('id')] = index;
        });

        $(this).sortable('cancel');

        controller.updateSortOrder(indexes);
      }
    });
  }
});
1
2
3
4
5
6
7
8
<!-- note, I am only using single {} because octopress eats handlebars tags -->
<ul class="sortable">
{#each item in controller}
  <li class="item" data-id="{unbound item.id}">
    <b>{item.idx}</b> {item.id}
  </li>
{/each}
</ul>

In order to bind the sortable plug-in to the DOM we use the didInsertElement function. This function is called when the view’s element is in the DOM and ready to be manipulated.

We call sortable on the list view that has the CSS class .sortable. This will bind jQuery UI’s sortable plug-in to our DOM element.

The only function we have to implement is the update function. This function is called when the sortable plug-in has finished sorting and the DOM is updated.

What we want to do in the update method is create an index of model ids with their new sort position. We can accomplish that by looping over the items in the list, grabbing the data-id and assigning it the value of the index.

Once we have created an index we need to cancel the sort. This is because we are going to update the model to reflect the new sort order.

Update Models

1
2
3
4
5
6
7
8
9
10
11
12
App.IndexController = Ember.ArrayController.extend({
  sortProperties: ['idx'],

  updateSortOrder: function(indexes) {
    this.beginPropertyChanges();
    this.forEach(function(item) {
      var index = indexes[item.get('id')];
      item.set('idx', index);
    }, this);
    this.endPropertyChanges();
  }
});

We can simply loop over the items in the array and update their idx. This will cause the list view to rerender with the correct sort order.

Fin

I hope this saves you some hair pulling and a bit of time.

You can see this in action in the playlist section at flowfeeds.com. You will need to sign up for an account to access it though, sorry.

Source Code Link

Source Code

Comments