8

I'm declaring a View like this:

var VirtualFileSelectorView = Backbone.View.extend({
    selected: function() {
        console.log("selected function");
    },

    initialize: function() {
        // Shorthand for the application namespace
        var app = brickpile.app;
        // bind to the selected event
        app.bind('selected', this.selected, this);
    }
});

Then I instantiate two instances of this View like you can see here: http://cl.ly/H5WI

The problem is that when the event selected is fired the function selected is called twice?

fguillen
  • 36,125
  • 23
  • 149
  • 210
marcus
  • 9,616
  • 9
  • 58
  • 108
  • I have edited your question, it looks more clear for me now but please check it out in case I have made a mistake – fguillen Jun 03 '12 at 20:23

2 Answers2

3

After read the comments thread I think I already understand how can I help with your issue:

In your code both Views are listening to the same global event, so both of them will respond at the same time, and you want to be able to trigger the selected() of each View in independent.

The usual approach to do this is that a View is associated with a Model, and the View is listening to the events on that Model, so events triggered for one Model only will affect to Views associate to it.

This pattern looks like this:

// code simplified and not tested
var MyView = Backbone.View.extend({
  initialize: function( opts ){
    this.model = opts.model;
    this.model.on( "selected", this.selected, this );
  },

  selected: function( model ){
    // ...
  }
})

var oneModel = new MyModel();
var oneView = new MyView({ model: oneModel });

Now you only have to take care of trigger the selected event on each Model when is needed.

Updated

This pattern is so common that Backbone associates the View.model reference for you so you can implement your View.initialize like this:

initialize: function(){
  this.model.on( "selected", this.selected, this );
}
fguillen
  • 36,125
  • 23
  • 149
  • 210
  • The View that I want to "listen" for the event in does not have the model available. This is the complete code that I'm using at the moment. If you look at line 134, this is the view I want to trigger from and on line 101 I want to be able to receive and set the value of model that I clicked. https://gist.github.com/2870026 – marcus Jun 04 '12 at 18:28
  • I see, I think you should need to make a more deeper change and think the architecture again. You should have an architecture such as that the _selected_ event is triggered on the Model and not in a global Object. – fguillen Jun 04 '12 at 18:45
1

As you have declared two instances of VirtualFileSelectorView you have two observers of the event selected.

Even if you are reusing the reference of the old View instance to make reference to the new View instance the old instance remains alive because there is still references targeting to it.

This is a very common issue in Backbone, I think people is starting to call it "ghosts Views".

To solve this you have to unbind all the events that the View is binding, in your example you can do:

app.virtualFileSelectorView.off( null, null, this );

Derick Bailey has an excellent post about this matter.

Also, with humility, I want to link to one study about this matter I did to try to understand this tenacious behavior.

Community
  • 1
  • 1
fguillen
  • 36,125
  • 23
  • 149
  • 210
  • should I add this line of code directly after I create my View instance? I tried it like this http://cl.ly/H5ww but the event still fires twice? – marcus Jun 03 '12 at 20:53
  • I always went with the "zombie" term. As mentioned, Derick Bailey's article on this and how to fix it is excellent. – jmk2142 Jun 04 '12 at 01:02
  • @fguillen I don't understand how and when I should apply off to my object. Maybe my question was unclear but I have two Views of the same type visible at the same time like this http://cl.ly/H8m6 , so the issue has nothing todo with jumping between pages. – marcus Jun 04 '12 at 13:53
  • @Marcus, so them it is completely normal that the event is fired twice. One time for each alive View. What do you expect? – fguillen Jun 04 '12 at 17:14
  • @fguillen I expected one event but I know now that I was wrong. What I'm trying to accomplish is that if I click the browse button, I open a dialog which is a backbone view and then I would like to listen to an event from this particular view so I can set the value of an hidden input on my VirtualFileSelectorView. So maybe I should go with different names on the events or is there a more suitable way of doing this with backbone? – marcus Jun 04 '12 at 17:33
  • @Marcus I have added another answer, check it out. – fguillen Jun 04 '12 at 17:44