6
votes

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. Leave Page and Stay on Page"

Can we invoke this confirmation box through some special function of browser? I want to implement it in AngularJS application

enter image description here

6
You must be aiming for window.confirm() method.EricG
@EricG that is not a confirm prompt in the screenshot.epascarello
@epascarello, Agreed, but actually it isnt obvious what he means. The "onbeforeunload" function cannot be invoked manually, but can be edited and this becomes clear 'whenever' it shows. The confirm dialog CAN be invoked manually but doesnt know by default whether or not the page was edited. So my answer wasnt that irrelevant compared to "onbeforeonload" I think ;)EricG
@SubRed - this isn't actually a duplicate question, when it comes to Angular. See my answer.Ben Lesh

6 Answers

11
votes

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

5
votes

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.

5
votes

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.

4
votes

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

1
votes

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';
        };
    });
})();
0
votes

I think you would need to use $window.alert or $window.confirm or beforeroutechange

Angular documentation