Reputation: 18351
In my Backbone.js app, I need to be able to insert new items between existing items in a collection. The examples I have found thus far on the web all seem to assume that new items should be appended to the end of a collection. That doesn't work for my purposes, so I've opted to rerender the entire collection when a new item is added.
However, the original items aren't removed from the view; instead, a duplicate set of items is appended to the end of the list. I'm able to work around this by using jQuery to clear the items prior to rendering, but that seems wrong.
Here's what I have right now:
Item = Backbone.Model.extend({
price: null,
});
Items = Backbone.Collection.extend({
model: Item,
initialize: function () {
this.add(new Item({ price: '$0.50' }));
this.add(new Item({ price: '$0.60' }));
this.add(new Item({ price: '$0.70' }));
}
});
ItemView = Backbone.View.extend({
tagName: 'li',
initialize: function () {
this.model.bind('change', this.render, this);
},
render: function () {
var item_template = _.template($('#item-template').html(), { item: this.model });
this.$el.html(item_template);
return this;
},
events: {
"click .copy-item": "copyItem",
},
copyItem: function (event) {
var index = itemlistview.collection.indexOf(this.model);
itemlistview.collection.add(new Item, { at: index + 1 });
},
});
ItemListView = Backbone.View.extend({
el: '#item-rows',
initialize: function () {
_.bindAll(this);
this.collection = new Items();
this.collection.bind('add', this.render);
this.render();
},
render: function () {
// It works if I uncomment the line below
//$('.item-row').remove();
var self = this;
this.collection.each(function (item) {
self.$el.append(new ItemView({ model: item }).render().el);
});
return this;
},
});
var itemlistview = new ItemListView;
And here's a jsFiddle that demonstrates the problem.
Is there a better way to handle this?
Upvotes: 4
Views: 4205
Reputation: 222188
As you're rerendering the whole thing, you do need to clear the old rendered inputs.
Altered ItemListView
ItemListView = Backbone.View.extend({
el: '#item-rows',
initialize: function () {
_.bindAll(this);
this.collection = new Items();
this.collection.bind('add', this.render);
this.render();
},
render: function () {
var self = this;
this.$el.empty()
this.collection.each(function (item) {
self.$el.append(new ItemView({ model: item }).render().el);
});
return this;
},
});
Upvotes: 4