Showing alert in angularjs when user leaves a page

122,479

Solution 1

The code for the confirmation dialogue can be written shorter this way:

$scope.$on('$locationChangeStart', function( event ) {
    var answer = confirm("Are you sure you want to leave this page?")
    if (!answer) {
        event.preventDefault();
    }
});

Solution 2

Lets seperate your question, you are asking about two different things:

1.

I'm trying to write a validation which alerts the user when he tries to close the browser window.

2.

I want to pop up a message when the user clicks on v1 that "he's about to leave from v1, if he wishes to continue" and same on clicking on v2.

For the first question, do it this way:

window.onbeforeunload = function (event) {
  var message = 'Sure you want to leave?';
  if (typeof event == 'undefined') {
    event = window.event;
  }
  if (event) {
    event.returnValue = message;
  }
  return message;
}

And for the second question, do it this way:

You should handle the $locationChangeStart event in order to hook up to view transition event, so use this code to handle the transition validation in your controller/s:

function MyCtrl1($scope) {
    $scope.$on('$locationChangeStart', function(event) {
        var answer = confirm("Are you sure you want to leave this page?")
        if (!answer) {
            event.preventDefault();
        }
    });
}

Solution 3

Here is the directive I use. It automatically cleans itself up when the form is unloaded. If you want to prevent the prompt from firing (e.g. because you successfully saved the form), call $scope.FORMNAME.$setPristine(), where FORMNAME is the name of the form you want to prevent from prompting.

.directive('dirtyTracking', [function () {
    return {
        restrict: 'A',
        link: function ($scope, $element, $attrs) {
            function isDirty() {
                var formObj = $scope[$element.attr('name')];
                return formObj && formObj.$pristine === false;
            }

            function areYouSurePrompt() {
                if (isDirty()) {
                    return 'You have unsaved changes. Are you sure you want to leave this page?';
                }
            }

            window.addEventListener('beforeunload', areYouSurePrompt);

            $element.bind("$destroy", function () {
                window.removeEventListener('beforeunload', areYouSurePrompt);
            });

            $scope.$on('$locationChangeStart', function (event) {
                var prompt = areYouSurePrompt();
                if (!event.defaultPrevented && prompt && !confirm(prompt)) {
                    event.preventDefault();
                }
            });
        }
    };
}]);

Solution 4

As you've discovered above, you can use a combination of window.onbeforeunload and $locationChangeStart to message the user. In addition, you can utilize ngForm.$dirty to only message the user when they have made changes.

I've written an angularjs directive that you can apply to any form that will automatically watch for changes and message the user if they reload the page or navigate away. @see https://github.com/facultymatt/angular-unsavedChanges

Hopefully you find this directive useful!

Solution 5

The other examples here work fine for the old versions of ui-router (>=0.3.x) but all state events, such as $stateChangeStart, are deprecated as of 1.0. The new ui-router 1.0 code uses the $transitions service. So you need to inject $transitions into your component then use the $transitions.onBefore method as the code below demonstrates.

$transitions.onBefore({}, function(transition) {
  return confirm("Are you sure you want to leave this page?");
});

This is just a super simple example. The $transitions service can accept more complicated responses such as promises. See the HookResult type for more information.

Share:
122,479
iJade
Author by

iJade

JavaScript enthusiast

Updated on July 08, 2022

Comments

  • iJade
    iJade almost 2 years

    I'm an angularjs new bee. I'm trying to write a validation which alerts the user when he tries to close the browser window.

    I have 2 links on my page v1 and v2.When clicked on the links it takes to the specific pages. Here is the code to redirect to v1 and v2

    angular.module('myApp', ['myApp.filters', 'myApp.services', 'myApp.directives'])
    
    .config(['$routeProvider', function($routeProvider) {
            $routeProvider.when('/v1', {templateUrl: 'pages/v_1.html', controller: MyCtrl1});
            $routeProvider.when('/v2', {templateUrl: 'pages/v_2.html', controller: MyCtrl2});
            $routeProvider.otherwise({redirectTo: '/v1'});
    }]);
    

    I want to pop up a message when the user clicks on v1 that "he's about to leave from v1, if he wishes to continue" and same on clicking on v2. Any pointers on how to achieve this would be appreciated.

    I got an answer here but it pops up the message after every time interval.

    Updated Code;

    Controllers

    function MyCtrl1() {
        $scope.$on('$locationChangeStart', function (event, next, current) {
            if ('your condition') {
                event.preventDefault();
    
                MessageService.showConfirmation(
                    'Are you sure?',
                MessageService.MessageOptions.YES_NO, {
                    'YES': function () {
                        blockNavigation = false;
                        $location.url($location.url(next).hash());
                        $rootScope.$apply();
                    },
                    'NO': function () {
                        MessageService.clear();
                        $log.log('NO Selected')
                    }
                });
            }
        });
    }
    MyCtrl1.$inject = [];
    
    
    function MyCtrl2() {}
    MyCtrl2.$inject = [];