Showing alert in angularjs when user leaves a page

JavascriptModel View-ControllerAngularjsAngularjs Directive

Javascript Problem Overview


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 = [];

Javascript Solutions


Solution 1 - Javascript

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 - Javascript

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

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

> 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 - Javascript

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 - Javascript

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 - Javascript

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.

Solution 6 - Javascript

$scope.rtGo = function(){
			$window.sessionStorage.removeItem('message');
			$window.sessionStorage.removeItem('status');
		}

$scope.init = function () {
			$window.sessionStorage.removeItem('message');
			$window.sessionStorage.removeItem('status');
		};

Reload page: using init

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestioniJadeView Question on Stackoverflow
Solution 1 - JavascriptScheintodView Answer on Stackoverflow
Solution 2 - JavascriptYair NevetView Answer on Stackoverflow
Solution 3 - JavascriptChristopher DaviesView Answer on Stackoverflow
Solution 4 - JavascriptfacultymattView Answer on Stackoverflow
Solution 5 - JavascriptBrent MatzelleView Answer on Stackoverflow
Solution 6 - JavascriptSrija NakkaView Answer on Stackoverflow