Reputation: 2386
So I have a bit of a problem.
I'm in a situation where I need to have multiple Backbone.Routers which handle their own routes accordingly etc. and I dynamically load them based on what the main router (Router 1 in the following example) knows about the route currently.
The main problem I am encountering though is something like this.
Is there any possible way I can get router2 to look at the current history fragment without potentially calling the routes in router1 again?
IE don't manually call Backbone.history.loadUrl(Backbone.history.getFragment());
Edit:
The main goal is that right now I have two views and well would obviously like a router per view. It makes no sense to have one huge router considering that in the future there may be n views that knows about every single individual view.
Upvotes: 1
Views: 1766
Reputation: 922
I suggest you try to look at MarionetteJS which is a great framework for building composite applications with Backbone. Specifically look at the source code of the MarionetteJS example app. What it does is separate the application into several sub-apps. Each sub-app has its own router, but they all define the separate routers on the parent app. When the parent app initializes, all routers are created, and only then Backbone.history.start()
is called. I realize that this answer requires you to dive into Marionette, which has a steep learning curve, but I think it's totally worth it. We've built the entire architecture of the SOOMLA designer web-app on top of it. Marionette has proven to be a great solution when you want to outgrow your repetitive Backbone boilerplate code. Kudos to Derick Bailey for an awesome open source framework.
Upvotes: 1
Reputation: 8293
Could you please provide a jsfiddle which reproduce your case? Because you could normally do that (I personally have an app instantiating a router, starting the history, instantiating several other ones, and it works perfectly fine.)
Until such time, here are some information about routers though:
- when you instantiate a router, the routes are bound to Backbone.history (one unique object)
- this implies that you can't expect both routers to execute a callback
- it also implies that there is a fixed order: the last instantiated router's routes will be checked first
Edit:
Ok, I guess you want both routes executed because you expect someone to get directly into tab1/stuff.
Ugly way: you can stop Backbone.history (Backbone.history.stop()) and start it right afterward, the router2's routes would be bound...
Other possibility: why don't you put all your routes in your main router? Well I guess if you really have too many that's understandable.
Last possibility (that I can think of): use the fact that the last router's routes are tested first, and that's what you need. Change your main router's routes, add a generic one that will catch what you need (for example tab1). Don't do anything, navigate backward to /tab1. Prepare 2 navigates, like this:
this.navigate('/tab1', {trigger: true});
this.once('someEvent', function() {
this.navigate('/tab1/stuff', {trigger: true});
});
If you have generic enough URLs, you can replace tab1 & stuff with arguments you would match with your generic route.
Edit 2:
Ok here's an edit assuming everything I wrote in my last comment and that you access your Backbone views with a hashtag (or an URL) like view/action. I'll try to be the more thorough as I can be (because I still don't have all the details of your problem).
This jsfiddle shows the principle. Now, there's still the fact that it will mess with the client's history (there may be a way to avoid that in Backbone I think, you'd have to look into that if it's a problem for you).
Now, the fact that there may be several other problems. The least of them could be the boilerplate in the secondary routers (you have to put view/ before any route). There are solutions for that, but that would be going too deep. The bigger one is the following:
I've already said it but only one route will be matched. So your main router CANT be used to deal with the fact the the client will change views (say going from view1/action1 to view2/action2, router2 already loaded before). The action2 will be executed, but if you reloaded your views in your main router, that won't be done.
Just as a last comment, you can modify the Routers core initialize method after creating your main router to add boilerplate behavior (reload your view?): here's an example that may suit you.
Upvotes: 0