Backbone.js : Remove an item from a collection
backbone.js, javascript
Solution
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.
Problem
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?