1

In the Backbone.js documentation, in the entry for the Router.routes method, it is stated

When the visitor presses the back button, or enters a URL, and a particular route is matched, the name of the action will be fired as an event, so that other objects can listen to the router, and be notified.

I have attempted to implement this in this relatively simple example:

The relevant JS:

$(document).ready(function(){
    // Thing model
    window.Thing = Backbone.Model.extend({
        defaults: {
            text: 'THIS IS A THING'
        }
    });

    // An individual Thing's View
    window.ThingView = Backbone.View.extend({
        el: '#thing',

        initialize: function() {
            this.on('route:showThing', this.anything);
        },

        anything: function() {
            console.log("THIS DOESN'T WORK! WHY?");
        },

        render: function() {
            $(this.el).html(_.template($('#thing-template').html(), {
              text: this.model.get('text')
            }));
            return this;
        }
    });

    // The Router for our App
    window.ThingRouter = Backbone.Router.extend({
        routes: {
            "thing":      "showThing"
        },

        showThing: function() {
            console.log('THIS WORKS!');
        }
    });

    // Modified from the code here (from Tim Branyen's boilerplate)
    // http://stackoverflow.com/questions/9328513/backbone-js-and-pushstate                                                             
    window.initializeRouter = function (router, root) {
        Backbone.history.start({ pushState: true, root: root }); 
        $(document).on('click', 'a:not([data-bypass])', function (evt) {

            var href = $(this).attr('href');
            var protocol = this.protocol + '//'; 

            if (href.slice(protocol.length) !== protocol) {
                evt.preventDefault();
                router.navigate(href, true);
            }
        });
        return router;   
    }

    var myThingView = new ThingView({ model: new Thing() });
    myThingView.render();
    var myRouter = window.initializeRouter(new ThingRouter(), '/my/path/');
});

The relevant HTML:

  <div id="thing"></div>

  <!-- Thing Template -->
  <script type="text/template" id="thing-template">
    <a class='task' href="thing"><%= text %></a>
  </script>

However, the router event referenced in the View's initialize function does not seem to get picked up (everything else works--I'm successfully calling the "showThing" method defined in the Router).

I believe I must have some misconception about what the documentation intended by this statement. Therefore, what I'm looking for in a response is: I'd love to have someone revise my code so that it works via a Router event getting picked up by the View, or, clearly explain what the Router documentation I listed above intends us to do, ideally with an alternative code sample (or using mine, modified).

Many thanks in advance for any assistance you can provide!

Charles
  • 50,943
  • 13
  • 104
  • 142
  • Shouldn't you be using `router.on('route:thing', this.anything);` in your initialize method? – WarFox Mar 03 '14 at 07:27

1 Answers1

3

This is beacuse you are binding a listener to the wrong object. Try this in your View :

window.ThingView = Backbone.View.extend({

    initialize: function() {
            myRouter.on('route:showThing', this.anything);
    },

...
drinchev
  • 19,201
  • 4
  • 67
  • 93
  • 2
    Okay, got it. I guess I was misinterpreting this part: "...so that other objects can listen to the router," somehow reading it as "...other objects can listen to Router *events*." I guess the implications of this are that, architecturally speaking, it's best to instantiate a global Router that views have the ability to reference as need be. Thanks drinchev! – Dave Della Costa Apr 02 '12 at 01:38