JohnD
JohnD

Reputation: 14757

Checking for unsaved changes when switching views in backbone.js

I am new to Javascript and backbone.js, so hopefully I am missing something simple here. I am experimenting with some sample code I found which is supposed to check for unsaved changes before allowing a user to navigate away to another page. I have created a JSfiddle here:

http://jsfiddle.net/U43T5/4/

The code subscribes to the hashchange event like this:

$(window).on("hashchange", router.hashChange);

And the router.hashChange function checks a "dirty" flag to determine whether or not to allow the navigation, like this:

hashChange: function (evt) {
    if (this.cancelNavigate) { // cancel out if just reverting the URL
        evt.stopImmediatePropagation();
        this.cancelNavigate = false;
        return;
    }
    if (this.view && this.view.dirty) {
        var dialog = confirm("You have unsaved changes. To stay on the page, press cancel. To discard changes and leave the page, press OK");
        if (dialog == true) return;
        else {
            evt.stopImmediatePropagation();
            this.cancelNavigate = true;
            window.location.href = evt.originalEvent.oldURL;
        }
    }
},

The problem is that the code is not working because this.view is undefined, so the 2nd if block is never entered.

I would like the sample program to always ask for confirmation before navigating away from the page (in my sample program, I have set this.view.dirty to always be true, which is why it should always ask for confirmation). Or if there is a better approach, I am open to alternatives.

Upvotes: 1

Views: 1534

Answers (2)

user2846569
user2846569

Reputation: 2832

I spent a lot of time to make at least something decent.

I ended up writing a wrapper for Backbone function:

    var ignore = false;

    Backbone.history.checkUrl = function() {

            if (ignore) {
                ignore = false;
                return;
            }

            app.dirtyModelHandler.confirm(this, function () {
                Backbone.History.prototype.checkUrl.call(Backbone.history);
            },
            function() {
                ignore = true;
                window.history.forward();

            });

    };

app.dirtyModelHandler.confirm is a function which shows confirmation (Ok, Cancel) view and takes success and cancel functions as arguments.

Upvotes: 0

Sushanth --
Sushanth --

Reputation: 55740

The main issue is the this context in the methods , this corresponds to the Window Object and not the Router. So it always remains undefined as you are defining view on the router. Declare a initialize method which binds the context inside the methods to router.

 initialize: function() {
        _.bindAll(this, 'loadView', 'hashChange');
    },

Check Fiddle

Upvotes: 1

Related Questions