diff --git a/src/collection-view.js b/src/collection-view.js index 9dffbb191f..1cf13d032f 100644 --- a/src/collection-view.js +++ b/src/collection-view.js @@ -145,9 +145,12 @@ Marionette.CollectionView = Marionette.View.extend({ if (modelsChanged) { this.render(); } else { - // get the DOM nodes in the same order as the models - var els = _.map(models, function(model) { - return children.findByModel(model).el; + // Get the DOM nodes in the same order as the models and reindex the + // views. + var els = _.map(models, function(model, index) { + var childView = children.findByModel(model); + childView._index = index; + return childView.el; }); // since append moves elements that are already in the DOM, diff --git a/test/unit/collection-view.spec.js b/test/unit/collection-view.spec.js index e17d5a2a3f..17d25dd309 100644 --- a/test/unit/collection-view.spec.js +++ b/test/unit/collection-view.spec.js @@ -310,7 +310,8 @@ describe('collection view', function() { foo: 'biz' }, { foo: 'baz' - }]); + } + ]); this.collection.comparator = function(model) { return model.get('foo'); }; diff --git a/test/unit/sorted-views.spec.js b/test/unit/sorted-views.spec.js index c6e47c8ac9..633cb8ca0b 100644 --- a/test/unit/sorted-views.spec.js +++ b/test/unit/sorted-views.spec.js @@ -472,6 +472,16 @@ describe('collection/composite view sorting', function() { expect(this.collectionView.$el).to.have.$text('321'); }); + it('should reindex the views', function() { + _.each(this.collectionView._filteredSortedModels(), function(model, index) { + expect(this.collectionView.children.findByModel(model)._index).to.equal(index); + }.bind(this)); + + _.each(this.compositeView._filteredSortedModels(), function(model, index) { + expect(this.compositeView.children.findByModel(model)._index).to.equal(index); + }.bind(this)); + }); + it('should triggerMethods events', function() { var cv = this.collectionView; if (specOptions.onPrototype) { @@ -492,5 +502,55 @@ describe('collection/composite view sorting', function() { describeSpec({asOption: true, viewComparator: true}); describeSpec({onPrototype: true}); describeSpec({onPrototype: true, viewComparator: true}); + + describe('when changing the comparator multiple times', function() { + beforeEach(function() { + this.collectionView = new this.CollectionView({ + childView: this.ChildView, + collection: this.collection, + reorderOnSort: true, + }); + + this.compositeView = new this.CompositeView({ + childView: this.ChildView, + collection: this.collection, + reorderOnSort: true, + }); + + this.collectionView.render(); + this.compositeView.render(); + }); + + it('should reorder the DOM', function() { + // Try ordering descending... + this.collection.comparator = function(a, b) { + if (a.get('foo') > b.get('foo')) { + return -1; + } else if (a.get('foo') < b.get('foo')) { + return 1; + } else { + return 0; + } + }; + this.collection.sort(); + expect(this.collectionView.$el).to.have.$text('321'); + expect(this.compositeView.$el).to.have.$text('321'); + + // ...then ascending. + this.collection.comparator = function(a, b) { + if (a.get('foo') < b.get('foo')) { + return -1; + } else if (a.get('foo') > b.get('foo')) { + return 1; + } else { + return 0; + } + }; + + this.collection.sort(); + expect(this.collectionView.$el).to.have.$text('123'); + expect(this.compositeView.$el).to.have.$text('123'); + }); + }); }); });