Pass added and removed models to collection update events

This commit is contained in:
Linus-A. M. Gubenis
2015-07-13 09:48:49 -05:00
committed by Graeme Yeates
parent 45f4ebaac1
commit 90cb566250
2 changed files with 136 additions and 7 deletions

View File

@@ -810,7 +810,10 @@
var singular = !_.isArray(models);
models = singular ? [models] : models.slice();
var removed = this._removeModels(models, options);
if (!options.silent && removed.length) this.trigger('update', this, options);
if (!options.silent && removed.length) {
options.removedModels = removed;
this.trigger('update', this, options);
}
return singular ? removed[0] : removed;
},
@@ -835,6 +838,7 @@
var set = [];
var toAdd = [];
var toMerge = [];
var toRemove = [];
var modelMap = {};
@@ -860,6 +864,7 @@
var attrs = this._isModel(model) ? model.attributes : model;
if (options.parse) attrs = existing.parse(attrs, options);
existing.set(attrs, options);
toMerge.push(existing);
if (sortable && !sort) sort = existing.hasChanged(sortAttr);
}
if (!modelMap[existing.cid]) {
@@ -908,7 +913,7 @@
// Silently sort the collection if appropriate.
if (sort) this.sort({silent: true});
// Unless silenced, it's time to fire all appropriate add/sort events.
// Unless silenced, it's time to fire all appropriate add/sort/update events.
if (!options.silent) {
for (i = 0; i < toAdd.length; i++) {
if (at != null) options.index = at + i;
@@ -916,7 +921,14 @@
model.trigger('add', model, this, options);
}
if (sort || orderChanged) this.trigger('sort', this, options);
if (toAdd.length || toRemove.length) this.trigger('update', this, options);
if (toAdd.length || toRemove.length || toMerge.length) {
options.changes = {
added: toAdd,
removed: toRemove,
merged: toMerge
};
this.trigger('update', this, options);
}
}
// Return the added (or merged) model (or models).

View File

@@ -716,6 +716,7 @@
[4, 0]);
assert.deepEqual(col.difference([c, d]), [a, b]);
assert.ok(col.includes(col.sample()));
var first = col.first();
assert.deepEqual(col.groupBy(function(model){ return model.id; })[first.id], [first]);
assert.deepEqual(col.countBy(function(model){ return model.id; }), {0: 1, 1: 1, 2: 1, 3: 1});
@@ -762,6 +763,7 @@
QUnit.test('reset', function(assert) {
assert.expect(16);
var resetCount = 0;
var models = col.models;
col.on('reset', function() { resetCount += 1; });
@@ -1821,7 +1823,7 @@
collection.remove([{id: 1}, {id: 2}]);
});
QUnit.test('remove does not trigger `set` when nothing removed', function(assert) {
QUnit.test('remove does not trigger `update` when nothing removed', function(assert) {
assert.expect(0);
var collection = new Backbone.Collection([{id: 1}, {id: 2}]);
collection.on('update', function() { assert.ok(false); });
@@ -1836,9 +1838,12 @@
});
QUnit.test('set does not trigger `update` event when nothing added nor removed', function(assert) {
assert.expect(0);
var collection = new Backbone.Collection([{id: 1}, {id: 2}]);
collection.on('update', function() { assert.ok(false); });
collection.on('update', function(col, options) {
assert.equal(options.changes.added.length, 0);
assert.equal(options.changes.removed.length, 0);
assert.equal(options.changes.merged.length, 2);
});
collection.set([{id: 1}, {id: 2}]);
});
@@ -1876,4 +1881,116 @@
assert.equal(collection.length, 0);
});
})();
QUnit.test("#3711 - remove's `update` event returns one removed model", function(assert) {
var model = new Backbone.Model({id: 1, title: 'First Post'});
var collection = new Backbone.Collection([model]);
collection.on('update', function(context, options) {
assert.strictEqual(options.removedModels[0], model);
});
collection.remove(model);
});
QUnit.test("#3711 - remove's `update` event returns multiple removed models", function(assert) {
var model = new Backbone.Model({id: 1, title: 'First Post'});
var model2 = new Backbone.Model({id: 2, title: 'Second Post'});
var collection = new Backbone.Collection([model, model2]);
collection.on('update', function(context, options) {
var removedModels = options.removedModels;
if (!removedModels || removedModels.length !== 2) assert.ok(false);
assert.ok(removedModels.indexOf(model) > -1 && removedModels.indexOf(model2) > -1);
});
collection.remove([model, model2]);
});
QUnit.test("#3711 - set's `update` event returns one added model", function(assert) {
var model = new Backbone.Model({ id: 1, title: 'First Post'});
var collection = new Backbone.Collection();
collection.on('update', function(context, options) {
var addedModels = options.changes.added;
if (!addedModels || addedModels.length !== 1) assert.ok(false);
assert.strictEqual(addedModels[0], model);
});
collection.set(model);
});
QUnit.test("#3711 - set's `update` event returns multiple added models", function(assert) {
var model = new Backbone.Model({ id: 1, title: 'First Post'});
var model2 = new Backbone.Model({id: 2, title: 'Second Post'});
var collection = new Backbone.Collection();
collection.on('update', function(context, options) {
var addedModels = options.changes.added;
if (!addedModels || addedModels.length !== 2) assert.ok(false);
assert.strictEqual(addedModels[0], model);
assert.strictEqual(addedModels[1], model2);
});
collection.set([model, model2]);
});
QUnit.test("#3711 - set's `update` event returns one removed model", function(assert) {
var model = new Backbone.Model({ id: 1, title: 'First Post'});
var model2 = new Backbone.Model({id: 2, title: 'Second Post'});
var model3 = new Backbone.Model({id: 3, title: 'My Last Post'});
var collection = new Backbone.Collection([model]);
collection.on('update', function(context, options) {
var removedModels = options.changes.removed;
if (!removedModels || removedModels.length !== 1) assert.ok(false);
assert.strictEqual(removedModels[0], model);
});
collection.set([model2, model3]);
});
QUnit.test("#3711 - set's `update` event returns multiple removed models", function(assert) {
var model = new Backbone.Model({ id: 1, title: 'First Post'});
var model2 = new Backbone.Model({id: 2, title: 'Second Post'});
var model3 = new Backbone.Model({id: 3, title: 'My Last Post'});
var collection = new Backbone.Collection([model, model2]);
collection.on('update', function(context, options) {
var removedModels = options.changes.removed;
if (!removedModels || removedModels.length !== 2) assert.ok(false);
assert.strictEqual(removedModels[0], model);
assert.strictEqual(removedModels[1], model2);
});
collection.set([model3]);
});
QUnit.test("#3711 - set's `update` event returns one merged model", function(assert) {
var model = new Backbone.Model({ id: 1, title: 'First Post'});
var model2 = new Backbone.Model({ id: 2, title: 'Second Post' });
var model2_v2 = new Backbone.Model({ id: 2, title: 'Second Post V2'});
var collection = new Backbone.Collection([model, model2]);
collection.on('update', function(context, options) {
var mergedModels = options.changes.merged;
if (!mergedModels || mergedModels.length !== 1) assert.ok(false);
assert.strictEqual(mergedModels[0].get('title'), model2_v2.get('title'));
});
collection.set([model2_v2]);
});
QUnit.test("#3711 - set's `update` event returns multiple merged models", function(assert) {
var model = new Backbone.Model({ id: 1, title: 'First Post'});
var model_v2 = new Backbone.Model({ id: 1, title: 'First Post V2'});
var model2 = new Backbone.Model({ id: 2, title: 'Second Post' });
var model2_v2 = new Backbone.Model({ id: 2, title: 'Second Post V2'});
var collection = new Backbone.Collection([model, model2]);
collection.on('update', function(context, options) {
var mergedModels = options.changes.merged;
if (!mergedModels || mergedModels.length !== 2) assert.ok(false);
assert.strictEqual(mergedModels[0].get('title'), model2_v2.get('title'));
assert.strictEqual(mergedModels[1].get('title'), model_v2.get('title'));
});
collection.set([model2_v2, model_v2]);
});
QUnit.test("#3711 - set's `update` event should not be triggered adding a model which already exists exactly alike", function(assert) {
var fired = false;
var model = new Backbone.Model({ id: 1, title: 'First Post'});
var collection = new Backbone.Collection([model]);
collection.on('update', function(context, options) {
fired = true;
});
collection.set([model]);
assert.equal(fired, false);
});
})();