47

I want to set a default route for my backbone.js controller. Currently I do it like so:

class DealSearchController extends Backbone.Controller
    routes:
        'list' : 'showListView'
        'photos' : 'showPhotoView'
        'map' : 'showMapView'

    initialize: ->
        ....        
            window.location.hash = 'list' if ! _.include( _.keys(@routes),(window.location.hash || '').replace('#',''))

Is there a better way of doing it?

Martin Wawrusch
  • 780
  • 1
  • 5
  • 12
  • Just as a note, if you are setting up your router with `@route path, ->` then order matters. More general routes should be first, eg default route should be first, otherwise it will be always triggered, obscuring your more specific routes. It's a bit couter intuitive to me :) – Tad Lispy Dec 16 '14 at 11:47

2 Answers2

88

Try adding this additional route as the last route in your controller:

'*path':  'defaultRoute'

and then handle it like this:

defaultRoute: function(path) {
    this.showListView();
}

This assumes the list route is your preferred default. This should work since Backbone.js will match the routes in order, but will always match the 'splat' route.

Bill Eisenhauer
  • 6,143
  • 2
  • 28
  • 28
  • This is generally a good solution, as long as the iteration order matches the declaration order in the object literal. – init_js Nov 17 '15 at 02:04
2

You may use the splat route format to define a catch-all route, such as:

routes:
  'list' : 'showListView'
  '*path': 'defaultRoute'

defaultRoute: ->
  ...

These splats can match any number of URL components. Since the one given here essentially matches anything, the order in which the routes are defined matters. Earlier rules listed in the routes literal take precedence over later ones. So the catch-all rule should be listed last.

A note of warning: The mechanics of the for in statement leave the iteration order of keys in objects unspecified (ECMA-262 section 12.6.4):

The mechanics and order of enumerating the properties ... is not specified.

Most browsers, if not all with some buggy exceptions, will iterate in order of definition. If the routes defined have ambiguity whose correct resolution rely on ordering (like in this case), and/or if an explicit ordering may be preferable because of an unpredictable environment, it is also possible to define routes dynamically in the Router's initializer, rather than declaratively/statically:

initialize: function () {
    //router.route(route, name, [callback]);
    this.route('*path', 'default', this.defaultRoute);
    this.route('map', 'map', this.showMapView);
    this.route('photos', 'photos', this.showPhotoView);
    this.route('list', 'list', this.showListView);
}

In this case, routes defined later override previously-defined routes, so the order from earlier is reversed to preserve the same behaviour.

init_js
  • 2,780
  • 16
  • 41