Reputation: 36068
Generally when design view for Collection(s), I would bind the collection
to the view, and register related events to the collection
like this:
var Book = Backbone.Model.extend({});
var BookList = Backbone.Collection.extend({
model: Book,
url: "/books"
});
var BookListItemView = Backbone.View.extend({
mtemplate: _.template($('#tpl_book_item').html()),
render: function () {
this.$el = $(this.mtemplate(this.model.toJSON()));
return this;
}
});
var BookListView = Backbone.View.extend({
el: '#content',
initialize: function () {
this.listenTo(this.collection, 'add', this.render);
this.listenTo(this.collection, 'remove', this.render);
},
render: function () {
this.$el.empty();
this.collection.each(function (item) {
this.$el.append(new BookListItemView({model: item}).render().$el);
}, this);
return this;
}
});
Use:
var books = new BookList();
var bookListView = new BookListView({
collection: books
});
books.fetch();
It worked as expected: render every book as defined in the template. However I found that there is a slight stuck in the page.
I am not sure if this is caused by the re-rendering the view? As shown, when the books.fetch
complete, it will add books to the collection of books
, for each book
item, an add
event will be triggered, then I will re-render the page by removing the exist item and iterate the collection.
Which means once there are 10 books, there will be 1+2+3+4...+10
loops for the BookListView
.
I my opinion, once the add
event triggered, I should not refresh the whole list but just add a new view to the BookListView
, but how about the remove
event, it seems that Backbone does not provide any internal method to get the view from the model, so once a model to be removed, I can not get the related view.
How do you handle this kind of suitation?
Upvotes: 0
Views: 181
Reputation: 687
Do not bind your add
to the render
function. Instead create a dedicated add method for that.
var Book, BookList, BookListItemView, BookListView;
Book = Backbone.Model.extend({});
BookList = Backbone.Collection.extend({
model: Book,
url: "/books"
});
BookListItemView = Backbone.View.extend({
mtemplate: _.template($("#tpl_book_item").html()),
initialize: function() {
this.model.on("remove", this.remove);
},
render: function() {
this.$el = $(this.mtemplate(this.model.toJSON()));
return this;
}
});
BookListView = Backbone.View.extend({
el: "#content",
initialize: function() {
this.listenTo(this.collection, "add", this.addItem);
},
render: function() {
this.$el.empty();
this.collection.each((function(item) {
this.addItem(item);
}), this);
return this;
},
addItem: function(item) {
this.$el.append(new BookListItemView({
model: item
}).render().$el);
}
});
Let the models own View handle its own remove event.
Upvotes: 2