Below is the code so far
The accepted answer is great, however I had an issue with properly getting a handle on my form controller consistently since some forms I use the form
tag with the name
attribute and at other times i use the ng-form
directive. Also, if you're using typescript style functions utilizing the this
or vm
type pattern e.g.
I'm surprised no one else has mentioned this, but my fix was to utilize the require property of the directive and let angular give me a reference to the form controller itself.
I've updated the accepted answer below to show my changes, notice the require property and the additional parameter to the link function.
angular.module("myApp", []).directive('confirmOnExit', function() {
return {
restrict: 'A',
require: 'form',
link: function($scope, elem, attrs, form) {
window.onbeforeunload = function(){
if (form.$dirty) {
return "The form is dirty, do you want to stay on the page?";
}
}
$scope.$on('$locationChangeStart', function(event, next, current) {
if (form.$dirty) {
if(!confirm("The form is dirty, do you want to stay on the page?")) {
event.preventDefault();
}
}
});
}
};
});
With this I can guarantee that I have a good handle on the form controller because angular will throw an error if it cannot find a form controller on the element.
You can also add modifiers like ^ and ? such as require='^form'
to pull an ancestor form or require='?form'
if the form is optional (this wont break the directive, but you will need to check that you have a handle on a valid form controller yourself).