4

I have this structure of views:

window.templateLoaderView = Backbone.View.extend({});

window.PopupView = templateLoaderView.extend({
   initialize: function () {
       this.PopupModel = new PopupModel();
       this.event_aggregator.bind("tasks_popup:show", this.loadTaskPopup);
   },

   render: function() {
       template= _.template($('#'+this.PopupModel.templateName).html());
       $(this.el).html(template(this.PopupModel.toJSON()));
       $('#'+this.PopupModel.containerID).html(this.el);
   },

   loadTaskPopup: function() {
       this.PopupModel.loadTemplate("popupTask_templateHolder", "/js/templates/popup_task.html", "1", "container_dialog");
       this.render();
   }
});

window.TaskbarView = templateLoaderView.extend({

   initialize: function () {
       this.TaskbarModel = new TaskbarModel();
       this.PopupModel = new PopupModel();
   },

   loadTaskbarPopup: function() {
       this.event_aggregator.trigger("tasks_popup:show");
   }

});

So I would like to runf function in one view form another. As far as I understand, I need to bind them somehow. Is it possible to bind them in initialize function?

I saw here example: Backbone.js - Binding from one view to another? . They creating both objects and than somehow binding them.

Thanks in advance,

Community
  • 1
  • 1
kaha
  • 1,417
  • 2
  • 17
  • 21

1 Answers1

12

I am kind of a fan of using the "Event Aggregator" pattern. I make sure that every view is given a copy of the same event aggregator object and they can all talk to each other through it... kind of like a CB radio :)

Do this before you create any views:

Backbone.View.prototype.event_aggregator = _.extend({}, Backbone.Events);

Now, you can publish/subscribe from anywhere:

window.PopupView = Backbone.View.extend({
    initialize: function() {
        _.bindAll(this, "loadTaskPopup");
        this.model = new PopupModel();
        this.event_aggregator.bind("tasks_popup:show", this.loadTaskPopup);
    },

    loadTaskPopup: function() {
        // do something with this.model
    }
});

window.TaskbarView = Backbone.View.extend({
    loadTaskbarPopup: function() {
      this.event_aggregator.trigger("tasks_popup:show")
    }
});
Brian Genisio
  • 47,787
  • 16
  • 124
  • 167
  • Thank you Brian, I tried to do it the way you showed me, but I guess because of the structure of my models and views, it didn't work. Firebug throwing me this error **this.PopupModel is undefined**, when I'm accessing this function from TaskbarView. Do you know how can I solve it? – kaha Oct 10 '11 at 15:41
  • Yes. Your new problem is unrelated. You haven't bound the `loadTaskPopup` function to be in the context of your object. Look at the `_.bindAll` call that I added to the `PopupView.initialize`. It will cause `loadTaskPopup` to be called with a context (`this`) of your object so that the function can resolve `this.PopupModel`. – Brian Genisio Oct 10 '11 at 16:16
  • I'd also add that from an idiomatic perspective, you should not create a property called `PopupModel` but it should be `model` instead. It is also odd that your model is loading a template... but I will let you figure that one out on your own. :) – Brian Genisio Oct 10 '11 at 16:20
  • Thanks Brian, it worked :) Just two questions. What if 1 view will have 2 models? how would you name it? The reason why model is loading template is because, there some functions which load templates from localStorage (and if it is not there, than getting template from .html file and saving it to localStorage). More info is here: http://stackoverflow.com/questions/7542089/best-way-to-load-asynchronously-undescore-templates . Do you think this is not logical? Thank you for all your help :) – kaha Oct 10 '11 at 17:07
  • 1
    Using a model to load data from local storage is certainly logical. Even if that data happens to be a template. I wouldn't worry too much about it. As for having two models, that is usually an indication that your view is doing too much. Usually there is a primary model that your view is acting upon. If there is another model, it is often for support. I would still try to keep to one `model` and bring anything in as a special name. This may be the case in your code... I was just noticing a common problem... but that doesn't mean you are necessarily doing it wrong. Does that help? – Brian Genisio Oct 10 '11 at 17:18
  • Great thanks Brian. I think it all make sense. I didn't use yet 2 models in one view, but I thought that it might happen, so in order not confuse myself, I was giving these names )) I just start learning it, but it getting more clear now :) – kaha Oct 10 '11 at 17:32
  • This was a great bit of code and a nice approach.. thanks for posting. – Duncan_m Sep 11 '12 at 00:29
  • where should you place that top bit of code, event_aggregator? – mheavers Oct 30 '13 at 18:16
  • I usually put that in the app creation. – Brian Genisio Oct 30 '13 at 23:53