Drag & Drop Sorting With Ember.js & jQuery Sortable

Turns out implementing jQuery sortable into an Ember.js project (which persists sort changes) is easy.

View: Enable jQuery sortable

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) {
        //Cancel default action
        $(this).sortable('cancel');

        //Collect new placements
        var indexes = {};
        $(this).find('.sorted-item').each(function(index) {
          indexes[$(this).data('id')] =index;
        });
        controller.updateSort(indexes);
      }
    });
  }
});

First, we use the didInsertElement event (called when the view has been inserted into the DOM (link)), to bind sortable.

On sortable update, we want to list all .sortable-item’s and find their new position. Pending on your App structure, this may be a DOM iterator or something much cleaner.

Now, all we need to do is persist the sorted changes.

Controller: Persist sort changes

1
2
3
4
5
6
7
8
9
10
11
App.IndexController = Ember.ArrayController.extend({
  updateSort: function(indexes) {
    this.beginPropertyChanges();
      this.forEach(function(model) {
        var pos = indexes[model.get('id')];
        model.set('position', pos);
        model.save();
      }, this);
    this.endPropertyChanges();
  }
});

Very simple (again, your implementation will probably be tigher when no written for a blog). Wrapping multiple changes in beginPropertyChange and endPropertyChanges simply defers notifications until all changes are finished (link).

All we need to do is iterate each model in the ArrayController, and update the position property based on the new indexes. In this case, that property is titled ‘position’.