Reputation: 261
I have a very complex Backbone application with many views/Models and collections.
at times when user clicks a button I need to update multiple collections and update certain views.
In order to manage the collections I've handled most events in my router. The sequence of events is as follows:
user clicks a link/button and view triggers an event:
this.model.trigger('someEvent');
the model listening to the event, updates itself if necessary and notifies the router through my eventbus
eventbus.trigger('globalEVent');
My router is listening to global events, fetches collections/models from a cached storage and updates the necessary collections and models.
This has worked really well so far but
I have just too many events and my router code is becoming hard to manage. My question is there a way to handle events outside of the router and still access methods inside the router? is my approach correct or is there a more elegant solution I haven't considered?
Update:
Here's how I do it now:
in Router I call this method in my initialize():
registerModules : function() {
var self = this;
Backbone.trigger(Events.RegisterModule, function(moduleRoutes) {
_.each(moduleRoutes, function(moduleRoute) {
self.routeDetails[moduleRoute.name] = {
buildPageUrl: moduleRoute.buildPageUrl,
fragment : moduleRoute.fragment
}
self.route(moduleRoute.fragment, moduleRoute.name, moduleRoute.action);
});
});
},
Then I have regular self-exec blocks for each module/page which self registers (simplified version):
(function() {
var module = {
loadAndDisplay: function() {},
saveAndContinue: function(model) {
Backbone.trigger(Events.ChangePage, model.get('nextPage'));
},
registerEvents: function() {},
_init: function() {
module.registerEvents();
var self = this,
routes = [{
fragment: Constants.FRAGMENT,
name: Constants.PAGE_NAME,
buildPageUrl: function() {
return Constants.FRAGMENT;
},
action: module.loadAndDisplay
}];
Backbone.on(Events.RegisterModule, function(registerCallback) {
registerCallback.call(registerCallback, routes);
});
}
};
module._init();
})();
Of course your Router script should load before your module code. It works great for my needs. With this design I have separated router / modules completely and they have no knowledge of each other either. Each will handle it's own events/data etc. Shared logic goes in router.
Upvotes: 1
Views: 293
Reputation: 111032
You should split you router functionality into different classes. In our Marionette based application we using a RegionManager to handle all the view related stuff, like change views in different areas, open overlays etc and a StateMachine. The router itself just trigger different events, like state:change or region:change where the manager classes listen to.
Doing it tis way, you can have a different manager classes that handle a special aspect of your app. Let the router to what he is build for: listen on location change events and notify the app about it. The router should not have other logic then this.
Upvotes: 1