bleyk
bleyk

Reputation: 799

AngularJS $locationChangeStart Event Cancelling Route Navigations

Can Someone please help me out understand how to use the $locationChangeStart Event? Im making aa function that if a user clicks the browser back button without saving the data on the form in that specific page, a modal popup will show saying that there is unsaved changes and ask the user to save it. I searched for different explanations and I cant understand some of them. I was trying to look for a sample demo but I cant find any. Btw, Im using html and angularjs Thanks in advance

Upvotes: 1

Views: 4482

Answers (1)

Sunil Lama
Sunil Lama

Reputation: 4539

The $locationChangeStart is fired when AngularJS starts to update browser's location based on differences done via $location service ($location.path(), $location.search()).

It might happen that an application will listen to the $locationChangeStart event and will call preventDefault() on it. In this case the second event ($locationChangeSuccess) won't be broadcasting.

$locationChangeStart fires when the location gets updated. It is followed by $locationChangeSuccess if the first action wasn't prevented.

The difference in $routeChangeSuccess and $locationChangeSuccess is that $routeChangeSuccess fires once a route has successfully changed and the $locationChangeSuccess fires when the URL is changed but before the route changes. Note that this isn't all URL changes, just times the URL changes in a way that the AngularJS application can register it (for example, a setter call to $location.url()). You use scope.$on('$locationChangeSuccess') for that.

You can create a flag for form saved or not and then on the basis of that flag value you can start a popup, which will inform the user for the back navigation or stay on the same page.

i would recommend stateChangeStart,

onRouteChangeOff = $rootScope.$on('$stateChangeStart', routeChange);

    function routeChange(event, newState) {
        //Navigate to newUrl if the form isn't dirty
        if (!$rootScope.unsavedChanges) return;
        event.preventDefault();
        var modalOptions = {
            closeButtonText: 'Cancel',
            actionButtonText: 'Ignore Changes',
            headerText: 'Unsaved Changes',
            bodyText: 'You have unsaved changes. Leave the page?'
        };

        ModalService.showModal({}, modalOptions).result.then(function () {
            $rootScope.unsavedChanges = false;
            $state.go(newState); //Go to page they're interested in
        });
    }

For $locationChangeStart:

onRouteChangeOff = $rootScope.$on('$locationChangeStart', routeChange);

function routeChange(event, newUrl, oldUrl) {
    //Navigate to newUrl if the form isn't dirty
    if (!$rootScope.unsavedChanges) return;

    var modalOptions = {
        closeButtonText: 'Cancel',
        actionButtonText: 'Ignore Changes',
        headerText: 'Unsaved Changes',
        bodyText: 'You have unsaved changes. Leave the page?'
    };

    ModalService.showModal({}, modalOptions).result.then(function () {
            $rootScope.unsavedChanges = false;
            $location.path(newUrl); //Go to page they're interested in
        }
    , function () {
        event.preventDefault();
    });         
    return;
}

Example Reference: http://youku.io/questions/1862163/angularjs-ui-router-onlocationchangestart-event-preventdefault-does-not-work

To handle the $locationChangeStart event you can use the $scope.$on() function (in a controller for example) or you can use $rootScope.$on() (in a factory or service for example). For this example I’ve added a call to $on() into a function that is called immediately after the controller is invoked to watch for location changes. That means you can use this code for the particular controller of that page, meaning no code in the html side rather it is invoked, when the location changes from that particular controller's page.

Upvotes: 4

Related Questions