1

I'm a newbie to angularjs.Is there any way to show alert when a form has unsaved data and user presses browser back button. Any pointers to how to achieve this would be appreciated.

Update: :

    angular.module('myApp.directives', []).directive('confirmOnExit', function() {
    return {
        link: function($scope, elem, attrs) {


            $scope.$on('$locationChangeStart', function(event, next, current) {

                if ($scope.myForm.$dirty) {
                    if(!confirm("Ahh the form is dirty, do u want to continue?")) {
                        event.preventDefault();
                    }
                }
            });

            window.onbeforeunload = function(){
                alert('me');
                if ($scope.myForm.$dirty) {
                    return "The Form is Dirty.";
                }
            }
        }
    };
});

Updated code

    angular.module('myApp.directives', []).directive('confirmOnExit', function () {
    return {
        link: function ($scope, elem, attrs, $rootScope) {
            window.onbeforeunload = function () {
                if ($scope.myForm.$dirty) {
                    return " do you want to stay on the page?";
                }
            }

            $rootScope.$watch(function {
                return $location.path();
            },

            function (newValue, oldValue) {
                if (newValue != oldvalue) {
                    // here you can do your tasks
                } else {}
            },
            true);

            $scope.$on('$locationChangeStart', function (event, next, current) {
                if ($scope.myForm.$dirty) {
                    if (!confirm("The form is dirty, do you want to stay on the page?")) {
                        event.preventDefault();
                    }
                }
            });
        }
    };
});
iJade
  • 23,144
  • 56
  • 154
  • 243

2 Answers2

3

Yes, I just gave this answer some minutes ago to another user, create a watch at root scope level to catch location changing:

$rootScope.$watch(function() { // fixed function declaration
   return $location.path();
   },  
   function(newValue, oldValue) {  
      if (newValue != oldValue) { // Update: variable name case should be the same
         // here you can do your tasks
      }
      else {
      }
   },
   true);
Community
  • 1
  • 1
remigio
  • 4,101
  • 1
  • 26
  • 28
  • well i'm new to angular js so can u tell me where should i put this angularjs, in directive or controller portion,i'll post my existing code.Plz have a look – iJade Feb 15 '13 at 12:23
  • Just put the watch in the directive controller instead of the root scope – remigio Feb 15 '13 at 14:21
  • i just did dat but it shows error Uncaught SyntaxError: Unexpected token return at return $location.path() – iJade Feb 15 '13 at 14:24
  • i just updated the modified code as per ur suggestion above.Have a look – iJade Feb 15 '13 at 14:30
  • Exactly, anyway this is not the right place to chat, if you need further advise let's go to the chatroom. – remigio Feb 15 '13 at 14:32
  • Look at the definition of $watch on the angular [API doc](http://docs.angularjs.org/api/ng.$rootScope.Scope), it's a callback, Angular calls it with the old and new values of the watched variable. – remigio Feb 15 '13 at 18:23
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/24586/discussion-between-remigio-and-iblue) – remigio Feb 15 '13 at 18:25
  • here is a better solution to detect browser back button: http://stackoverflow.com/questions/19686169/angularjs-redirect-a-route-only-on-browsers-back-button – morph85 Apr 08 '15 at 03:59
1

As you've discovered, you can write a custom directive to watch for changes. Your updated code is on track, however there are a few things you could do to improve:

  1. Your directive references the form by name, which limits it's re-usability. For example, what if you wanted to use this same directive on a form called myOtherForm? Currently using $scope.myForm.$dirty limits this flexibility. Instead, a better approach is to bind to the formController in your linking function.

  2. There really isn't a need to watch $location.path() since binding to $locationChangeStart will do the same thing.

I've written an angularjs directive that you can uses the approaches I've discussed above. @see https://github.com/facultymatt/angular-unsavedChanges

Hopefully you find this directive informative. Feel free to learn from it or even use it in your project.

facultymatt
  • 169
  • 1
  • 3
  • 8