If user tries to leave unsaved edited form, a message box pop-up
\"This page is asking you to confirm that you want to leave - data you have entered may not be saved. Le
I think you would need to use $window.alert
or $window.confirm
or beforeroutechange
Angular documentation
You can easily protect your form with jQuery with this simple unobtrusive code. Put in just before your </body>
closing tag.
(function () {
jQuery('form').one('change', function () {
window.onbeforeunload = function () {
return 'Form protection';
};
});
})();
If you want to cancel the route change when you determine your form is dirty, you can do this:
$rootScope.$on('$locationChangeStart', function(event) {
event.preventDefault();
});
This will cancel the routing and keep you on the current page.
You could use the "onbeforeunload" event. The syntax is as follows:
window.onbeforeunload = function () {
return "Your text string you want displayed in the box";
}
This event will popup that confirmation dialog that you described above asking whether or not the user truly wants to leave the page.
Hope this helps.
I liked @blesh's answer, but I think it fails to account for internal url changes (for example, if you use ngView on your application and visit different internal views). window.onbeforeunload never gets called when the hash # changes. In this case, you have to listen to both window.onbeforeunload and $locationChangeStart:
app.controller('OtherCtrl', ['$scope', '$window', '$location', '$rootScope', function($scope, $window, $location, $rootScope) {
$scope.message = "This time you get a confirmation.";
$scope.navigate = function() {
$location.path("/main");
}
var getMessage = function() {
if($scope.myForm.$dirty) {
return $scope.message;
} else {
return null;
}
}
$window.onbeforeunload = getMessage;
var $offFunction = $rootScope.$on('$locationChangeStart', function(e) {
var message = getMessage();
if(message && !confirm($scope.message)) {
e.preventDefault();
} else {
$offFunction();
}
});
}]);
See plunkr here: http://plnkr.co/edit/R0Riek?p=preview
Warlock's answer is partly right, but in doing so, you'd break testability.
In Angular, you'd want to use $window, and you'll want to watch $dirty
on your form. You'll need to have a named form, notice name="myForm"
below. Then you can $watch
$dirty
on the form in your $scope
:
app.controller('MainCtrl', function($scope, $window) {
$scope.name = 'World';
var win = $window;
$scope.$watch('myForm.$dirty', function(value) {
if(value) {
win.onbeforeunload = function(){
return 'Your message here';
};
}
});
});
HTML
<form name="myForm">
Name: <input type="text" ng-model="name"/>
</form>
Here's a plunk to demonstrate: http://plnkr.co/edit/3NHpU1