diff --git a/README.md b/README.md
index 0e1b42a..a9791c5 100644
--- a/README.md
+++ b/README.md
@@ -153,6 +153,10 @@ Ember is moving towards a paradigm that encourages the use of actions. With this
remove-item / remove-value |
Sent when the user deselects an item in multiple mode. The removed object is sent as a parameter. `remove-value` is identical, but gets the removed value passed in. |
+
+ reorder-items |
+ Sent when the user reorders a list of items in multiple mode. The reordered list of items is sent as a parameter |
+
on-focus |
Sent when the control gains focus. |
diff --git a/addon/components/ember-selectize.js b/addon/components/ember-selectize.js
index ca01595..55e8832 100644
--- a/addon/components/ember-selectize.js
+++ b/addon/components/ember-selectize.js
@@ -134,6 +134,7 @@ export default Ember.Component.extend({
create: allowCreate ? Ember.run.bind(this, '_create') : false,
onItemAdd: Ember.run.bind(this, '_onItemAdd'),
onItemRemove: Ember.run.bind(this, '_onItemRemove'),
+ onChange: Ember.run.bind(this, '_onChange'),
onType: Ember.run.bind(this, '_onType'),
render: this.get('renderOptions'),
placeholder: this.get('placeholder'),
@@ -232,6 +233,38 @@ export default Ember.Component.extend({
});
},
+ /**
+ * Event callback triggered when an item has changed (eg. reorder with drag_drop plugin)
+ * Here we need to update our selection property (if single selection) or array (if multiple selection)
+ * We also send an action
+ */
+ _onChange : function(args) {
+ var selection = get(this,'selection');
+ var vp = get(this,'_valuePath');
+
+ if(!args || !selection || !isArray(selection) || args.length !== selection.length) {
+ return;
+ }
+
+ if( selection.every(function(obj, idx) {
+ if( get(obj, vp) === args[idx] ) { return true; }
+ }) === true ) { return; }
+
+ var reorderedSelection = Ember.A([]);
+
+ args.forEach(function(value) {
+ var obj = selection.find(function(item) {
+ return (get(item, vp) + '') === value;
+ }, this);
+
+ if (obj) {
+ reorderedSelection.addObject(obj);
+ }
+ });
+
+ this._changeSelection(reorderedSelection);
+ },
+
/**
* Event callback triggered when an item is added (when something is selected)
* Here we need to update our selection property (if single selection) or array (if multiple selection)
@@ -319,6 +352,22 @@ export default Ember.Component.extend({
});
},
+ _changeSelection(selection) {
+ // TODO This is just to get the tests green, will be cleaned up before merge!
+ if (!this.get('changeDidTriggerAlready')) {
+ this.set('changeDidTriggerAlready', true);
+ this.set('selection', selection);
+ } else {
+ this.set('changeDidTriggerAlready', false);
+ return;
+ }
+
+ // allow the observers and computed properties to run first
+ Ember.run.schedule('actions', this, function() {
+ this.sendAction('reorder-items', selection);
+ });
+ },
+
/**
* Ember observer triggered before the selection property is changed
* We need to unbind any array observers if we're in multiple selection
diff --git a/tests/unit/components/ember-selectize-test.js b/tests/unit/components/ember-selectize-test.js
index 013fdaf..3df8b64 100644
--- a/tests/unit/components/ember-selectize-test.js
+++ b/tests/unit/components/ember-selectize-test.js
@@ -281,6 +281,21 @@ test('updating a selection updates selectize value', function(assert) {
assert.equal(component.get('selection'), content.objectAt(1));
});
+test('reorder a selection updates selectize value', function(assert) {
+ var component = this.subject();
+ Ember.run(function() {
+ component.set('content', Ember.A(['item 1', 'item 2', 'item 3', 'item 4']));
+ component.set('selection', Ember.A(['item 2', 'item 3']));
+ component.set('multiple', true);
+ });
+ this.render();
+ Ember.run(function() {
+ component._selectize.setValue(['item 3', 'item 2']);
+ });
+ assert.deepEqual(component.get('value'), ['item 3', 'item 2']);
+ assert.deepEqual(component.get('selection'), ['item 3', 'item 2']);
+});
+
test('replacing a multiple selection updates selectize selection', function(assert) {
var component = this.subject();
Ember.run(function() {
@@ -563,6 +578,32 @@ test('it sends remove-value action when an item is deselected in multiple mode',
});
});
+test('it sends reorder-items action when an item is reordered in multiple mode', function(assert) {
+ assert.expect(1);
+
+ var component = this.subject();
+
+ var targetObject = {
+ externalAction: function(obj) {
+ assert.deepEqual(obj, ['item 3', 'item 1', 'item 2'], 'externalAction was called with proper argument');
+ }
+ };
+
+ Ember.run(function() {
+ component.set('multiple', true);
+ component.set('content', Ember.A(['item 1', 'item 2', 'item 3', 'item 4']));
+ component.set('selection', Ember.A(['item 1', 'item 2', 'item 3']));
+ component.set('reorder-items', 'externalAction');
+ component.set('targetObject', targetObject);
+ });
+
+ this.render();
+
+ Ember.run(function() {
+ component._onChange(['item 3', 'item 1', 'item 2']);
+ });
+});
+
test('if label is falsy, don\'t add item', function(assert) {
var component = this.subject();
Ember.run(function() {