I've been facing an issue for the entire day now, and I'm kind of desperate! I'm pretty sure this will be simple for some Backbone experts around here...I'm new with Backbone and I might have not taken the best approach. Any help or advice will be awesome!
The Issue
After adding a new item to a collection, the collection is re-rendered, and I can see the new item added to my DOM. If I click on the 'remove' button the event gets fired, and the new item get destroyed...BUT the element stays in the DOM. If I re render the page, (refresh or navigate somewhere else and come back) it's gone.
Whereas if I add a new item, navigate somewhere else right after my collection get rendered, then come back, and press 'remove', this time it gets destroyed AND removed from the DOM... Any idea?
Adding a new item
save: function(e){
e.preventDefault();
var data = form2js('deviceForm', '.', true);
//Allow to create or edit a model;
this.model.set(data);
this.model = this.collection.create(this.model, {
wait: true,
success: function(){
Utils.alert('success', 'Device has been added/edited');
app.vent.trigger("devices:show");
}
});
}
this code is inside the view shown when I add a new item. When the new item gets added, it calls the function below. this.collection is my list of devices, reused inside the router.
Router
showDevices: function(){
if (!this.devices){
this.devices = new Devices();
this.devices.fetch();
}
if (this.devicesList) this.devicesList.remove();
this.devicesList = new DevicesView({collection: this.devices});
$('.addPadding').hide().slideDown(1000, 'linear').html(this.devicesList.render().el);
},
I fetch the list just once and then reuse it every time I need it, avoiding unnecessary fetch. I clean the view if existing and instantiate a new one.
Collection (View)
initialize: function(){
_.bindAll(this, "render", "addOne");
this.collection.on('add', this.addOne);
this.collection.on('reset', this.addAll);
},
render: function(){
this.$el.html(this.template);
this.addAll();
return this;
},
addOne:function(device){
var devi = new DeviceView({model: device});
this.$el.find(".devices-list").append(devi.render().el);
},
addAll: function(){
this.collection.each(this.addOne, this)
}
no el attribute defined in my collection view. binding to collection event so that it gets rendered for a new item or fetch done.
Item view
tagName: 'tr',
events: {
'click .remDevice': 'removeDevice',
'click .editDevice' : 'editDevice'
},
template: _.template( template ),
initialize: function(){
this.listenTo(this.model, 'destroy', this.remove);
},
render: function(){
this.$el.html(this.template(this.model.toJSON()));
return this;
},
removeDevice:function(){
this.model.destroy();
}
My items are appended into a table, to the tbody element. This table is inside the template of my collection view. When I click on the remove button, the model is destroyed and the event is fired and call this.remove. But doesn't works when the collection is re rendered just after the creation of the item. Works after though...
Hope I gave enough information! Thanks a lot in advance! PS: No error in the console and model + collections are populated in my debugger.
EDIT: this.remove is called at each click since my model gets destroyed every time. By overriding it and trying to remove manually the element with:
this.$el.remove();
makes no difference and doesn't show any error. this.$el contains my newly added element.
EDIT 2 A new clue: If I've a collection of 6 devices, add a 7th, then try to delete ANY of them, they got destroyed but not removed of the DOM unless I do the re render. So it's not linked to the NEW item only, but to the fact I added a new item to the collection, rendered it and try to delete one Item. Also, the EDIT function still works on each item and redirect me to the right page with the right model to edit.
LAST EDIT I tried to empty the collection before to add new Items to avoid zombies...but didn't change anything. I hoped it would have avoided random side effects in my Collection View
addAll: function(){
this.$el.find(".devices-list").empty();
this.collection.each(this.addOne, this)
},
_.bindAll(this, "render", "addOne");what is that line doing? does it work if you remove that? - Mike Vormwaldthisparameter to yourcollection.on()lines, you won't need the_.bindAllstuff. I try to stay away from using_.bindAll- Cory Danielsonthis.model.on('all', function(eventName){console.log(eventName)});then check the console to see what events are being fired. You really just need to figure out why thatdestroyevent is not trigging theremovefunction. Once you solve that, I think you'll solve your problem. I've deleted my answer, because it wasn't a solution. - Cory Danielson