The accepted answer is great, but I had a problem getting the handle on my form controller correctly, because in some forms I use the form tag with the name attribute and in other cases I use the ng-form directive. Also, if you use typescript style functions that use a template such as this or vm for example, <form name='$ctrl.myForm'...
I am surprised that no one else mentioned this, but I decided to use the require property of the directive and let angular give me a link to the form controller itself.
I updated the accepted answer below to show my changes, note the require property and an additional parameter for 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(); } } }); } }; });
In doing so, I can guarantee that I have a good handle on the form controller, because angular will throw an error if it cannot find the form controller on the element.
You can also add modifiers like ^ and ? for example require='^form' to retrieve the ancestor form or require='?form' if the form is optional (this will not violate the directive, but you will need to verify that you have a handle to the actual form controller yourself),
Dillon Aug 02 '18 at 20:50 2018-08-02 20:50
source share