Mpondomise Mpondomise - 3 months ago 32
AngularJS Question

angularjs app to redirect after login

Currently, when the users logs in, the login page does't redirect to the homepage.

'use strict';

angular.module('myapp').service('auth', function auth($http, API_URL, authToken, $state, $window, $q) {
function authSuccessful(res) {
authToken.setToken(res.token);
$state.go('main');
}

this.login = function (email, password) {
return $http.post(API_URL + 'login', {
email: email,
password: password
}).success(authSuccessful);
}

this.register = function (email, password) {
return $http.post(API_URL + 'register', {
email: email,
password: password
}).success(authSuccessful);
}


However, I have set my
$state.go
to redirect to main. Where is the problem? why is it not redirecting?

annex



here is my login.js controller, how it looks:

angular.module('myapp').controller('LoginCtrl', function ($scope, alert, auth, $auth) {

$scope.submit = function () {
$auth.login({
email: $scope.email,
password: $scope.password
})
.then(function(res) {
var message = 'Thanks for coming back ' + res.data.user.email + '!';
if (!res.data.user.active)
message = 'Just a reminder, please activate your account soon :)';

alert('success', 'Welcome', message);
})
.catch(handleError);
}
// i forgot to include this error handler in my code:
function handleError(err) {
alert('warning', 'oops there is a problem!', err.message);
}
});

Answer

Since this is an async action, angular doesn't know when the action finishes and thus when to update the $scope. For this to work you'll need to manually call $scope.apply(), but since you don't have access to the $scope in your service, you need to move the redirection logic (i.e. $state.go('main')) inside a controller, and call it like this:

angular.module('myapp').controller('LoginCtrl', function($scope, auth, $state) {

 function redirect(res) {
    $state.go('main');

    // manually update the scope
    $scope.$apply();
  }

  auth.login(email, password)
      .success(redirect);
});

EDIT: Integrate with the given controller

angular.module('myapp').controller('LoginCtrl', function ($scope, alert, auth, $auth) {

    $scope.submit = function () {
        $auth.login({
          email: $scope.email,
          password: $scope.password
        })
            .then(function(res) {
              var message = 'Thanks for coming back ' + res.data.user.email + '!';
              if (!res.data.user.active) {
                message = 'Just a reminder, please activate your account soon :)';
              }

              alert('success', 'Welcome', message);

              return null;
            })
            .then(function() {
              $state.go('main');

              // manually update the scope
              $scope.$apply();
            })
            // google replacement of the above commented out code bit
            .catch(handleError);
      }
    });

EDIT 2: Use $timeout instead of $scope.$apply so you don't get $digest error.

angular.module('myapp').controller('LoginCtrl', function ($scope, alert, auth, $auth, $timeout) {

    ...
    .then(function() {
      // $timeout calls $scope.$apply() by default, 
      // but it does it in a safely manner - never throws a '$digest already in progress' exception 
      $timeout(function() {
         $state.go('main');
      });
    })
    ...