threejeez
threejeez

Reputation: 2324

Backbone Collection Add Event Firing Once

I have a Backbone collection and when I add a new model to it the "add" event doesn't seem to work as I'd expect. I've bound 2 views to listen for add events on the collection, but only one seems to get notified of the event, and when this happens, no PUT request is sent to my server. When I remove the second bind, the other one works and the PUT request is sent. Here's the code snippets:

    var FlagList = Backbone.Collection.extend({
    model: Flag  // model not shown here... let me know if it would help to see
});

    var FlagCollectionView = Backbone.View.extend({
    el: $('ul.#flags'),
    initialize: function() {
        flags.bind('add', this.addFlag, this);  // this one doesn't fire!!
    },
    addFlag: function(flag) {
        alert("got it 1");  // I never see this popup
    }
});

    var AddFlagView = Backbone.View.extend({
    el: $("#addFlagPopup"),
    events: {
        "click #addFlag": "addFlag"
    },
            initialize: function() {
                    flags.bind('add', this.closePopup, this);   // this one fires!!
            }
    addFlag: function() {
        flags.create(new Flag);
    },
    closePopup: function() {
        alert("got it 2");  // I see this popup
    }
});

var flags = new FlagList;
var addFlagView = new AddFlagView;
var flagCollectionView = new FlagCollectionView;

Upvotes: 1

Views: 5060

Answers (3)

sirch
sirch

Reputation: 56

If you ended up here after making the same stupid mistake I did, make sure you've got:

this.collection.bind( 'add', this.render )

and NOT:

this.collection.bind( 'add', this.render() )

Upvotes: 1

Vincent Briglia
Vincent Briglia

Reputation: 3068

A few suggestions:

ID's vs Classes

you've over qualified your selector by combining a class and an id. jQuery allows this, but the ID selector should be unique on the page anyway so change el: $('ul.#flags') to el: $('ul#flags').

Leveraging Backbone

I like to explicitly pass my collections and/or models to my views and use the magic collection and model attributes on views.

var flags = new FlagList;
var addFlagView = new AddFlagView({collection: flags});
var flagCollectionView = new FlagCollectionView({collection: flags});

which now means that in your view, you will automagically have access to this.collection

unbinding events to avoid ghost views

var FlagCollectionView = Backbone.View.extend(
{
    initialize: function (options)
    {
        this.collection.bind('add', this.addFlag, this);
    },
    addFlag: function (flag)
    {
        alert("got it 1");
    },
    destroyMethod: function()
    {
        // you need some logic to call this function, this is not a default Backbone implementation
        this.collection.unbind('add', this.addFlag);
    }
});

var AddFlagView = Backbone.View.extend(
{
    initialize: function ()
    {
        this.collection.bind('add', this.closePopup, this);
    },
    closePopup: function ()
    {
        alert("got it 2");
    },
    destroyMethod: function()
    {
        // you need some logic to call this function, this is not a default Backbone implementation
        this.collection.unbind('add', this.closePopup);
    }
});

It looks like I have to agree with @fguillen, that your problem must be somewhere in how you initialize the view, as in my comment I mention that it's most likely related to timing, ie: binding your event to the collection after the 'add' event has already fired.

Upvotes: 6

fguillen
fguillen

Reputation: 38772

This code works for me:

var FlagList = Backbone.Collection.extend({});

var FlagCollectionView = Backbone.View.extend({
  initialize: function() {
    flags.bind('add', this.addFlag, this); 
  },
  addFlag: function(flag) {
      alert("got it 1");
  }
});

var AddFlagView = Backbone.View.extend({
  initialize: function() {
    flags.bind('add', this.closePopup, this);
  },
  closePopup: function() {
    alert("got it 2");
  }
});

var flags = new FlagList;
var addFlagView = new AddFlagView;
var flagCollectionView = new FlagCollectionView;

flags.add({key:"value"});

check the jsFiddle

Your problem is somewhere else.

Upvotes: 4

Related Questions