Search code examples
javascriptjquerybackbone.js

Backbone router function goto doesn't exist


I'm working on an example that I found on codepen. The example is about creating back button functionality. The problem I'm having is when the page loads the App.Router doesn't know about the goto function it says it's Uncaught TypeError: this.goto is not a function. I've gone over the example quite a few times to try and resolve this but I can't seem to get it to work at all. The example is on codepen and my working example is here

My problem is that the router doesn't know about the goto function that I put in there.

Your help would be much appreciated

code:

<!DOCTYPE html>
<html>
<head>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.2.1/backbone-min.js"></script>
    <script type="text/javascript">
        (function() {

            window.App = {
                Models: {},
                Views: {},
                Extensions: {},
                Forms: {},
                Controllers: {},
                Router: null,
                linkClicked: false,
                routes: [],
                backDetected : false,
                previousFragment : null,

                init: (route) => {
                    new App.Router();
                    this.instance = new App.Views.App();

                    Backbone.history.start();

                }
            }

            App.Router = Backbone.Router.extend({
                routes: {
                  '': 'home'
                },
                execute: function(callback, args) {
                    var self = this,
                        answer = $.Deferred(),
                        route = Backbone.history.getFragment();

                    if (route === '') {
                        route = 'home';
                    }

                    App.backDetected = false;

                    if (App.routes[App.routes.length - 2] === route && !App.linkClicked) {

                        App.backDetected = true;
                        App.routes.pop();

                        if (App.routes[App.routes.length - 1] === route) {
                            App.routes.pop();
                        }

                    }

                    if (App.routes[App.routes.length - 1] !== route) {
                        App.routes.push(route);
                    }

                    _.delay(function() {
                        // this is super hacky but need a delay as global event on links
                        // takes ages to execute
                        App.linkClicked = false;
                    }, 500);

                    answer.promise().then(function() {

                        App.dirty = false;

                        window.onbeforeunload = null;

                        if (callback) {
                            callback.apply(self, args);
                        } else {
                            console.log('no callback');
                        }
                    });

                    if (App.dirty) {
                        console.log('app is dirty');

                        window.onbeforeunload = (function(_this) {

                        })(this);

                    } else {
                        answer.resolve();
                    }
                },
                initialize: function(options) {
                    var self = this;
                    this.options = options || {};
                },
                goto: function(view, params) {
                    console.log('goto');
                    console.log(App.instance);
                },
                home: (query) => {
                    console.log('home');
                    let view = new App.Views.Home();
                    this.goto(view); // doesn't work
                }           
            });

            App.Extensions.View = Backbone.View.extend({
                goto: function(view) {
                    console.log('showing view');
                }
            });

            App.Views.App = App.Extensions.View.extend({

            })

            App.Views.Home = App.Extensions.View.extend({

            });

        })();



        $(function() {
          //new App.Router();

          window.App.init();



        }); 
    </script>
    <title></title>
</head>
<body>

</body>
</html>

Solution

  • The home function is using an arrow function which binds the context of this. Thus the window object is probably what is getting bound (instead of the router) and goto doesn't exist on that. Changing it to a normal function fixes it.

    home: function(query) {
      console.log('home');
      let view = new App.Views.Home();
      this.goto(view); // doesn't work
    }