Reputation: 14757
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:
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
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
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');
},
Upvotes: 1