Backbone.js : Remove an item from a collection
I'm using backbone.js to implement a buddy list aka Roster. My backbone view for the Roster collection and individual rosterEntry
are as follows:
Slx.Roster.Views.RosterEntry = Backbone.View.extend({
tagName: "li",
className : "rosterEntry clearfix",
templateSelector: '#rosterEntryTemplate',
initialize: function() {
_.bindAll(this, 'render');
this.model.bind('change', this.render);
this.model.bind('remove', this.remove);
this.template = _.template($("#rosterEntryTemplate").html());
},
remove: function () {
debug.log("Called remove event on model");
$(this.el).remove();
},
render: function() {
var renderedContent = this.template(this.model.toJSON());
this.id = this.model.Id;
$(this.el).attr('id', "friendid-" + this.model.get("id")).html(renderedContent);
return this;
}
});
Slx.Roster.Views.Roster = Backbone.View.extend({
el: "div#roster-container",
initialize: function () {
_.bindAll(this, 'render', 'add', 'remove');
this.template = _.template($("#rosterTemplate").html());
this.collection.bind('reset', this.render);
this.collection.bind('add', this.add);
this.collection.bind('remove', this.remove);
},
add: function (rosterEntry) {
var view = new Slx.Roster.Views.RosterEntry(
{
model: rosterEntry
});
$(this.el).append(view.render().el);
},
remove: function (model) { // if I ommit this then the whole collection is removed!!
debug.log("called remomve on collection");
},
render: function () {
var $rosterEntries, collection = this.collection;
$(this.el).html(this.template({}));
$rosterEntries = this.$('#friend-list');
_.each(collection.models, function (model) {
var rosterEntryView = new Slx.Roster.Views.RosterEntry({
model: model,
collection: collection
});
$(this.el).find("ul#friend-list").append(rosterEntryView.render().el);
}, this);
return this;
}
})
I'm testing for now using the Firebug console and can populate the roster just fine by executing the following:
collection = new Slx.Roster.Collection
view = new Slx.Roster.Views.Roster({collection:collection})
collection.fetch()
Adding to a collection also works fine, by executing the following in the Firebug console:
collection.add(new Slx.Roster.Model({username:"mickeymouse"})
and the new rosterEntry
is added to the Roster.
My problem is that collection.remove(5)
removes from the in-memory collection, but does nothing to update the DOM.
Strangely, if I ommit the remove()
function from the Roster View, all the entries in the roster are removed. If I add this method with nothing in it but a console log, it the remove method on both the Roster and RosterEntry
views is called - although I'm not sure why but they are out of order!
["Called remove event on model"]
["called remomve on collection"]
if I delete the remove function from the RosterEntry model I get this error:
TypeError: this.$el is undefined
this.$el.remove();
What am I doing wrong? How do I remove the element from the DOM when it is removed from the collection?
I think you have a problem with the context
in every event bind definition.
Try to change this:
this.model.bind('remove', this.remove);
For this:
this.model.bind('remove', this.remove, this);
I know you have tried to solve this with the bindAll
, but bindAll
is wrapping every call to the listed methods with the context of the actual object, but this can't do anything if you are calling the same method on other object :).
Updated
I have reading more.. looks like bindAll
and the third paramater of the bind
command do exactly the same. So maybe you can use the one or the other.
The because is not working the bindAll
in the model.remove
is because you forgot to add it to the _.bindAll(this, 'render')
line, look in your code. And my suggestion fixed it because as I say both approachs do the same.
What all this is doing is assuring that the calls to the listed methods ( render, remove, ...
in one case or this.remove
in the other) are gonna interpretate this
as a reference to the actual object. This can look stupid but this
is very volatile in JS.
Don't worry if you are still confused with the this
thing, I have dealing with it for long and still not completely cofindent.
Maybe essais like this can help us.
Have you tried the following?
this.listenTo(this.model, "remove", this.remove);
That seems to work for me and I like the way it reads a little bit better.
Link to Backbone doc
The remove methods on both the views are probably being called because you've bound to remove on both the model and the collection.
In RosterEntry:
this.model.bind('remove', this.remove);
In Roster:
this.collection.bind('remove', this.remove);
链接地址: http://www.djcxy.com/p/48318.html