itachi
itachi

Reputation: 3597

AngularJS $location.path not redirecting

I have been looking for a solution, but I still can't get the $location.path() to work correctly.

The case is simple: after positive authentication, I'm trying to go back to the root address: /#/. The path in the address bar is changing, but the page doesn't. What is curious, when I press "Enter" in the address bar, the page reloads before going to the root address. And what is more curious, I have to hit enter multiple times before it actually redirects me to another page. That's weird, because that's not how the "one-page" approach is supposed to be working.

I'm using Angular Router, and the rest of the page is working correctly. Every screen is loading smoothly after typing its path and pressing "Enter" - no reloading. The only problem is with the authentication step.

When the app is firstly loaded, and the /login page is issued because there are no authentication details saved, the app can be redirected to the root address after positive authentication (yet not always). But when the authentication details are lost while the app is running, and the user is redirected to the /login page, the app just can't go back to the root URL.

I have created a flowchart, which presents how routes are changing. The green area presents the first case, when the user opens up the app and is not logged in yet. The read area presents the second case, when the user loses the authentication details for some reason (e.g. old token, changed password from another source). The user is redirected to /login page, and then after positive authentication, can't go back to the root URL.

Flowchart

I've tried to wrap $location.path('/') in $scope.$apply but received an error, that the digest is actually in progress. Wrapping it in $timeout didn't help as well. I can of course reload the page after changing the path, but it creates an ugly effect of disappearing interface.

Below is the code triggered after pressing the "Login" button.

function doLogin() {
    vm.loginInProgress = true;

    LoginService.login(vm.username, vm.password).then(function () {
        $location.path('/');
    }).catch(function () {
        var confirm = $mdDialog.confirm()
            .title('Authentication error')
            .textContent('Username and/or password is invalid.')
            .ariaLabel('Authentication error')
            .ok('OK')
            .cancel('Forgotten password?');

        $mdDialog.show(confirm).catch(function() {
            //TODO: Forgotten password
        })
    }).finally(function () {
        vm.loginInProgress = false;
    });
}

Routes:

$routeProvider
    .when('/login', {
        templateUrl: 'views/login.html',
        controller: 'LoginController',
        controllerAs: 'vm'
    })
    .when('/', {
        templateUrl: 'views/home.html',
        controller: 'HomeController',
        controllerAs: 'vm',
        resolve: {
            init: init
        }
    });

/* @ngInject */
function init(ConfigService, TemperatureService) {
var ret = {};

return ConfigService.finished()
    .then(function () {
        return TemperatureService.getSetPoint();
    })
    .then(function (data) {
        ret['setpoint'] = data;
        return TemperatureService.getWorkModes();
    })
    .then(function (data) {
        ret['workmodes'] = data;
        return ret;
    });
}

It looks like a weird behavior of location.path method. Or I'm just missing something. Every help will be appreciated.

Upvotes: 1

Views: 1267

Answers (2)

Sravan
Sravan

Reputation: 18657

In your question you have taken a resolve which executes the code given in that resolve function.

You must have some issue in that init function which you used for resolving.

$routeProvider
    .when('/login', {
        templateUrl: 'views/login.html',
        controller: 'LoginController',
        controllerAs: 'vm'
    })
    .when('/', {
        templateUrl: 'views/home.html',
        controller: 'HomeController',
        controllerAs: 'vm',
        resolve: {
            init: init
        }
    });

Your init can go here,

var init = function ($q, $rootScope, $location) {
    if ($rootScope.login) {
        return true;
    } else {
        $location.path('/login')  // this is a sample
    }
};

You may have some issue in this method. please check once.

Upvotes: 1

Tewson Seeoun
Tewson Seeoun

Reputation: 61

This is likely due to the resolve function init for the route / not resolving correctly.

You can try listening to the $routeChangeError event to see what went wrong.

$rootScope.$on('$routeChangeError', function () {
  ...
});

Upvotes: 0

Related Questions