backbone.js + global event dispatcher + require.js: how-to?
Asked Answered
P

2

16

I have a number of backbone models, organized in collections and connected to their corresponding views and/or collections of views. Some of these models that do not belong to the same collection need to trigger an event which is of interest to another model (and maybe more than one).

The recommended way to deal with this is, I think, the "global event dispatcher/aggregator" as described here and other places.

However, I also happen to be using require.js, which seems to go against the idea of attaching the dispatcher/aggregator to the application's namespace object -- or am I wrong here?

So my question is: using require.js how can I have a number of different backbone models trigger an event that will be handled by another model?

Pseudohermaphrodite answered 13/9, 2012 at 7:36 Comment(0)
C
35

A similar solution to what @Andreas proposed but without Backbone.Marionette (heavily inspired nonetheless, see the article linked in the question).

All you have to do is to define a module that creates a singleton of an event listener and require this object in the modules where you want to trigger an event or listen to this event.

Let's say you have app/channel.js defining your channel

define(['backbone', 'underscore'], function (Backbone, _) {
    var channel = _.extend({}, Backbone.Events); 
    return channel;
});

You can then use it as a listener via

require(['app/channel'], function (channel) {
    channel.on('app.event', function () {
        console.log('app.event');
    });
});

and you can trigger an event on this channel via

require(['app/channel'], function (channel) {
    channel.trigger('app.event');
});
Carbon answered 13/9, 2012 at 11:42 Comment(7)
I think that this is what I've been looking for. Thanks a lot nikoshr and andreasPseudohermaphrodite
What is the advantage of event usage in this situation? We still have to include "app/model" in all modules where we going to trigger that event. Why not to make an api call on that model?Conjectural
@wizardzloy The only module you have to include is app/channel where you want to listen to or trigger a global event. app/model is only there to demonstrate a sample usage.Carbon
@wizardzloy But I admit the examples might be confusing. I tried to reword my answer a bit, I hope it's clearer.Carbon
@Carbon But if we won't include the "app/model" that script won't be loaded at all. So we still have to include it somewhereConjectural
@wizardzloy You lost me. The question was about a global event handler and I hope my answer does address that. app/model was used as a (contrived and not very useful, indeed) demo and is now removed.Carbon
I think you should include underscore as well to get access to _.extend.Loch
I
1

We using Marionettes app.vent (which is the global event transmitter for our application), allong with require js and it works really well.

app

define(, function(){
  return new Backbone.Marionette.Application();
})

Model1

define(['app'], function(app){
  return Backbone.Marionette.Model.extend({
    initialize: function(){
      this.bindTo('app.vent', 'create:model2', this.toSomething, this);
    }
  })
})

Model2

define(['app'], function(app){
  return Backbone.Marionette.Model.extend({
    initialize: function(){
      app.vent.trigger('create:model2', this);
    }
  })
})
Immoderate answered 13/9, 2012 at 9:59 Comment(4)
Good to know that Marionette is OK with require.js. However is there no solution to the problem that doesn't involve an additional / alternative framework?Pseudohermaphrodite
There are a bunch of solutions. I can advice PubSubJS: github.com/mroderick/PubSubJSOsmond
Thanks for your suggestion, I'll have a look at it. But are there no solutions that do not involve any additional framework?Pseudohermaphrodite
There is no such thing in requirejs, so you have to use an additional framework or write by yourself.Osmond

© 2022 - 2024 — McMap. All rights reserved.