How to keep my backbone router DRY - backbone.js

I've got a router which serves up most of my main pages from a single route.
'myclasses/:id':'index',
'myclasses': 'index',
'classes/:id':'index',
'index':''
This all works pretty well, but the problem I'm having is that I need to figure out if the request came from myclasses or from classes as that will return a different result which I pass to my collection.
How can I get the requesting url, preferably without the :id, from within the index function?

try Backbone.history.fragment.

Related

Backbone - Get Router parameter and reload same route

I have a table and I'm deleting a row. When I delete this row, I want to reload the current Backbone route, but few things to take in count:
e.g I'm in this route
"oneurl#order-by-name/page-8"
If the table, at that page, has only one record and I delete it, I would like to redirect to #order-by-name/page-7, so I need to get the "page" parameter. If there are still records, I want to "reload" the same route (to add next page's row if there are). It seems is not possible (https://github.com/jashkenas/backbone/issues/1214).
Any ideas?
As discussed in the issue you link (mainly jashkenas's comment "trigger: true is usually a code smell"), you shouldn't really be using routes like that for a javascript application.
What you should be doing instead:
have somewhere to store the current application's state (e.g. a plain javascript object) which is passed to the function taking care of displaying the views and data you want
when a row is deleted, modify the application state object (e.g. changing the current page attribute) and call the same function as above, once again passing in the configuration
update the url with navigateonly if the fragment should change
In reverse, your router should parse the url fragment to generate a configuration object discussed above, and call the function to render the views (passing in the configuration info).
For more on how to manage routing without using trigger: true everywhere, take a look at http://lostechies.com/derickbailey/2011/08/03/stop-using-backbone-as-if-it-were-a-stateless-web-server/ and the free preview to my book (on Marionette, but the same applies to Backbone) which also contains a chapter discussing route handling.

Is there a way to stop a Backbone Router?

Is it possible to close or stop a Backbone Router from listening to its defined routes?
I ask because I have been testing Backbone SubRoute (https://github.com/ModelN/backbone.subroute), setting up an application that has many spaces in which a user could have many subapplications running.
As such, I have defined a a main router, subrouter structure that follows roughy:
MainRouter = Backbone.Router.extend
routes:
"":"root"
"spaces/:id/:module(/*subroute)":"invokeModule"
root: () ->
console.log "root trigger"
invokeModule: (id, module, subroute) ->
that = this
GigaApp.module(module).start({nested_root: "spaces/#{id}/#{module}"})
SubAppRouter = Backbone.SubRoute.extend
routes:
"":"app_home"
app_home: () ->
console.log 'at sub app home'
SubApp.on "start", (options) ->
SubApp.router = new SubAppRouter(options.nested_root)
This general structure works from the first time a sub application is initialized for a space, as the MainRouter starts the SubApp, which initializes its router with the correct nested route. Subsequently, other routes defined in the SubAppRouter also trigger fine.
However, if you navigate to a different space (of different id), and navigate back to the first space, this structure breaks because the SubAppRouter already initialized for that space overrides the MainRouter, and no call the start the SubApp is made from the MainRouter.
So, I'm wondering if there is a way to stop or disable unbind the route triggering of a Backbone router.
As of this moment, the answer is NO
Derick Bailey opened this issue on Backbone's repo suggesting some changes to backbone's structure to support such a change: https://github.com/jashkenas/backbone/pull/1630
There followed a discussion of the merits of such a change, where the following point was made:
To get started -- I'm afraid that I don't understand the premise here. There are a couple axioms of routing that contradict this patch:
Routers exist to match URLs to locations in your application.
The whole point of URLs is that they're always reachable -- once you have a URL, you can go back to it (bookmark it, paste it into a browser) at any point.
I also went over the Backbone source code, and there is no indication that the functionality I am thinking about is possible.
I'm curious why you're not using the AppRouter in Marionette? It should solve your problems regarding dividing routes into smaller AppRoute objects...
Have a look at BackboneRails for some screencasts on building large scale apps. It's not only relevant for devs using rails as backend. It gives a great way to layout your app structure in modules (each with their own App Routes). Highly recommendable.

Multiple Routers in a Backbone (maybe Marionette) app

I currently have defined multple routers for my Backbone app (non-Marionette yet).
authRouter = new AuthRouter()
usersRouter = new UsersRouter()
...
# then to use them
authRouter.navigate "auth/login"
usersRouter.navigate "users/changePassword"
As you can see I am using the variables to navigate. So I must know which router to call. Is it possible to somehow organize code into separate classes but when I want to navigate, just call appRouter.navigate "something" instead of needing to know which router is it? Marionette recommends not having big routers but doesn't have a recommended way/example of it
If you look at the annotated source code for Backbone, you'll notice that calling myRouter.navigate is nothing more than a forwarding method call to Backbone.history.navigate
http://backbonejs.org/docs/backbone.html#section-114
So there's no need to keep track of routers for the navigate method. You can call Backbone.history.navigate directly.
Backbone.history.navigate "auth/login"

CakePHP Routing - params as actions

im having a problem with the CakePHP routing and the cookbook does not really help me out there.
im trying to route a parameter as a extension to an action. how can i do that without typing routes manually for each of my actions?
for example:
"users/settings/general" to UsersController::settings_general()
"users/settings/privacy" to UsersController::settings_privacy()
and so on
or should i just check in the settings action which parameter was given and call it from the controller? something like this
<?php
..
$sub_action = $this->request->params[0]
$this->settings_$subaction();
?>
I do not think this is possible without writing a custom route class. Read this article how to use and write your own route classe: http://mark-story.com/posts/view/using-custom-route-classes-in-cakephp
I would recommend you to just declare a direct route for each action. Or are you going to have thousands of these actions?
You could also try to route all users/settings/* to a single action UsersController::settings() and get the parameter there and call $this->setAction('settings' . $param); See http://api20.cakephp.org/class/controller#method-ControllersetAction

Preparing views when routing to initial route

I have a question about routing. The thing is, that I have trouble figuring out how to properly instantiate and render views when my app start for the first time on some route.
For example:
If a user accesses the app via the route /?#a/b/c
My app consists of different sections with subsections. This means that for the above route to work I have to render the view for section A before rendering and displaying the view for subsection B and at last render and display the view for subsubsection C.
The thing is, that this results in a bunch of ugly code in the various routing handlers
a: function(){
A.render();
}
b: function(){
A.render();
B.render();
}
c: function(){
A.render();
B.render();
C.render();
}
So I'm thinking that I'm approaching the problem the wrong way.
When introducing other Routers as the app grows this becomes even harder to maintain I would imagine.
A solution would be if there were an event being triggered before the callback for a route is called. But I can't find a such in the docs.
So my question is, how are these situations handled properly? Because my solution doesn't scale. Is there a way for a to always fire when visiting a "subroute"?
I haven't found a good way to do this but I'll share what I've done and it may or may not apply to your situation. What I wanted to do was have separate routers that respond to portions of the route but backbone doesn't work that way. Backbone will stop when it finds the first route that matches.
What I've done to handle it is to set up a router like this--notice the custom regex to define the route--hopefully it won't make your eyes bleed
initialize:
{
this.route(/([^\/]*)[\/]?([^\/]*)?[\/]?([^\/]*)?/, "renderViews", this.renderViews);
},
renderViews: function(mainView, subView, subSubView)
{
//here you can do something clever--mainView, subView and subSubView may or may not
// have values but they are the names of the views. route of "a/b" will pass
// ["a", "b", undefined] as your arguments
if (mainView)
(new App.Views[mainView]()).render();
if (subView)
(new App.Views[subView]()).render();
if (subSubView)
(new App.Views[subSubView]()).render();
}
I realize this isn't exactly what you're probably hoping for but it worked well for me in a project.
good luck

Resources