Search code examples
javascriptbackbone.jsbackbone-routing

How to do a route alias within a Backbone Router?


Having a route like 'dogs': 'process', I need to rewrite it to 'animals': 'process'.

Now, I need the router to recognize both routes, but always display the url like /animals, it is sort of aliasing, but could not find any info on how to solve this without placing an url redirect in 'process' handler.


Solution

  • I'm assuming that the real need for aliases is different than dogs to animals, so I'll answer regardless of if the use-case here is good or not. But if you don't want to change the hash but want to trigger different behaviors in the app, using the router is probably not the route to go.

    Route aliases don't really exist in Backbone, other than defining different routes using the same callback. Depending on your exact use-case, there are multiple ways to handle similar routes.

    Replace the hash

    To display the same hash for a generic route coming from different routes, use the replace option of the navigate function.

    routes: {
        'lions': 'animalsRoute',
        'animals': 'animalsRoute'
    },
    animalsRoute: function() {
        this.navigate("#/animals", { replace: true });
        // or using the global history object:
        // Backbone.history.navigate("#/animals", { replace: true });
    }
    

    then handle the animals route, regardless of which route was initially used to get in this callback.

    Some other answers or tutorials will say to use window.location.hash but don't. Manually resetting the hash will trigger the route regardless and may cause more trouble than it'll help.

    Different behaviors but showing the same route

    Just use different callbacks, both using the replace trick above.

    routes: {
        'lions': 'lionsRoute',
        'tigers': 'tigersRoute'
    },
    showGenericRoute: function() {
        this.navigate("#/animals", { replace: true });
    },
    tigersRoute: function() {
        this.showGenericRoute();
        // handle the tigers route
    },
    lionsRoute: function() {
        this.showGenericRoute();
        // handle the lions route
    }
    

    Notice the inexistent animalsRoute. You could add the route if there's a generic behavior if no specific animal is chosen.

    Use the route params

    If you want to know which animal was chosen but still use the same callback and remove the chosen animal from the hash, use the route params.

    routes: {
        'animals/:animal': 'animalsRoute',
    },
    animalsRoute: function(animal) {
        // removes the animal from the url.
        this.navigate("#/animals", { replace: true });
    
        // use the chosen animal
        var view = new AnimalView({ type: animal });
    }
    

    Redirect to the generic route

    If you want a different behavior but always show the same route, use different callbacks, then redirect. This is useful if the generic route is in another router instance.

    var Router = Backbone.Router.extend({
        routes: {
            'animals': 'animalsRoute'
        },
        animalsRoute: function() {
            // handle the generic behavior.
        }
    });
    
    var PussyRouter = Backbone.Router.extend({
        routes: {
            'lions': 'lionsRoute'
            // ...
        },
        lionsRoute: function() {
            // handle lions, then redirect
            this.navigate("#/animals", { trigger: true, replace: true });
        }
    });
    

    Using the trigger options will call the animalsRoute in the other router and the replace option will avoid making an entry in the history, so pushing the back button won't go to lions to get back to animals and being caught in the animals route.