I’m using backbone for the first time while re-designing a major feature of an application. The goal is to use the same backbone collection/view code to manage several different lists on the same page – the functionality is all the same, it’s just the data that changes.
So far I’ve had success but have discovered a problem that I can’t figure out. When you add a new item from a form input, the view handles it and calls the collection’s add function which saves it with ajax. When complete, the collection calls an “additem” event that is supposed to trigger the view to re-render.
However, what happens is that only the event from the most recently loaded view is called. Even if I totally change the event names so they’re prefixed and must be unique for each view – which baffles me.
A lot of code is stripped out but the offending parts are below. In this code example I was trying to prefix the events for each list type we need, but no matter what it’s calling the event on the wrong view.
// A collection is made to manage the data - saves to the server, loads, updates, etc
var ListItems = Backbone.Collection.extend({
initialize: function(models, options) {
this.url = options.url;
this.options = options;
},
/**
* We'll use a custom addItem handler so that we're not triggering
* events or ajax requests on .add(), since .fetch() uses it
*/
addItem: function(obj,ajax_elem){
self_col = this;
$.ajax({
type: 'POST',
url: this.options.add_url,
data: obj,
success: function(resp){
if(resp.success === true){
console.log('collection calls ep ' + self_col.options.ep+':addItem');
Backbone.Collection.prototype.add.call(self_col, {text:obj.text,id:resp.id} );
self_col.trigger(self_col.options.ep+':addItem');
} else {
self_col.trigger(self_col.options.ep+':error', resp.errors);
}
// ... rest of stuff
// View manages rendering the items to the page, etc
ListView = Backbone.View.extend({
initialize: function(){
self = this;
this.ep = self.$el.attr('id');
this.collection.bind(this.ep+":addItem",function(){
console.log('view thinks ep is: ' + self.ep+":addItem");
console.log(self.$el);
self.render();
$(window).trigger('Snowy:ajax:stop', self.$el.find(':submit'));
});
// Load the category list
categoryList = new ListView({
collection: new ListItems( INIT_CATEGORIES, {
ep: 'categories',
// other opts
}),
el: $("#categories")
});
The problem is, you’re using globals. For the
self = thistrick to work, you have to make them local variables to the functions assigning them so that the variables are captured in any closures created within the current context.Instead of
do
Same with
self_col