Backbone: Refresh the current route

I noticed that the backbone router's navigate method won't reload the current path.

For example the current route is /view1 and you call router.navigate('view1',{trigger:true});. It won't activate the route event again.

Here's the code I test:

<html>
<head>
    <title>Testing123</title>
    <script src="http://code.jquery.com/jquery.min.js" type="text/javascript"></script>
    <script src="http://underscorejs.org/underscore-min.js" type="text/javascript"></script>
    <script src="http://backbonejs.org/backbone-min.js" type="text/javascript"></script>
    <style type="text/css" media="screen">
        #box{
            width:400px;
            height:400px;
            background-color:red;
        }       
    </style>
</head>
<body>
    <button id='view1'>view1</button>
    <button id='view2'>view2</button>
    <br/>
    <div id='box'>

    </div>
    <script type="text/javascript" charset="utf-8" async defer>
        var SystemRouter = Backbone.Router.extend({

          routes: {
            "view1":"view1",
            "view2":"view2"
          },

          view1: function() {
            console.log('view1');
          },

          view2: function() {
            console.log('view2');
          }

        });

        var sys = new SystemRouter();
        Backbone.history.start({pushState: true, root: "/test/routing.html#/"});
        sys.navigate('view1');

        $('#view1').click(function(){
            sys.navigate('view1',{trigger:true});
        });

        $('#view2').click(function(){
           sys.navigate('view2',{trigger:true});
        }); 
    </script>
</body>
</html>

The code above will load /view1 path, which prints out 'view1'. But if you try to click the button to navigate to /view1 path, it will be ignored.

My question is: How do I call the route event if it is the same as the current path?


There are several things that would accomplish this. If you anticipate navigating to a route that is already in the url, then first check the current route fragment with Backbone.history.fragment and see if it is the same as the route you want to activate. If so, then you can do any of the following:

  1. You could just call the route method directly: sys.view1();

  2. You could set the fragment to another dead route, then back to the route you want.

    sys.navigate('someDeadRoute'); sys.navigate('view1',{trigger: true});

  3. You could stop and restart the router:

    Backbone.history.stop(); Backbone.history.start()

    This would pickup the route again and run it.

I think I would go with #1.


Rather than starting & stopping Backbone's history, you can call Backbone.history.loadUrl.

To refresh the current page:

Backbone.history.loadUrl(Backbone.history.fragment);

Or as a link handler:

// `Backbone.history.navigate` is sufficient for all Routers and will trigger the
// correct events. The Router's internal `navigate` method calls this anyways.
var ret = Backbone.history.navigate(href, true);

// Typically Backbone's history/router will do nothing when trying to load the same URL.
// But since we want it to re-fire the same route, we can detect 
// when Backbone.history.navigate did nothing, and force the route.
if (ret === undefined) {
    Backbone.history.loadUrl(href);
}