Robben_Ford_Fan_boy
Robben_Ford_Fan_boy

Reputation: 8720

Correct method to Redirect from $http.post in angularjs

Can you tell me what is the correct way to redirect to another page if $http.post returns a specific error code.

Just to add context, I want to redirect to another page if the user is not logged in or authorized to use the API.

  function getData(filter) {
     var deferred = $q.defer();
     var data = JSON.stringify(filter);

      $http.post('/myapp/api/getData', data)
         .success(function (data, status, headers, config) {
            deferred.resolve(data);
         })
              .error(function (error) {
                 deferred.reject(error);
              });

     return deferred.promise;
  }

Upvotes: 9

Views: 3300

Answers (7)

Gopinath Kaliappan
Gopinath Kaliappan

Reputation: 7359

First of all Nice Question , In this scenario You Can use $location , $state If it is external url You can use $window.location.href ... I would recommend $location and it is the best way ...

Please See the link for further Using $window or $location to Redirect in AngularJS

    function getData(filter) {
         var deferred = $q.defer();
         var data = JSON.stringify(filter);



    $http.post('/myapp/api/getData', data)
             .success(function (data, status, headers, config) {
                deferred.resolve(data);

if(data.errorcode==9999)  // Define Your  Error Code in Server
{

    $location.path('/login'); // You Can Set Your Own Router 

}             })
                  .error(function (error) {

    $location.path('/login'); // You Can Set Your Own Router 
                     deferred.reject(error);
                  });

         return deferred.promise;
      }

Preferably use $location or $state ...

Upvotes: 2

Chiru Adi
Chiru Adi

Reputation: 647

You can redirect to page on unauthorized access of a user based on the status code which you can return from your API call.

$http({
method: "POST",
url: 'Api/login',
headers: {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'}
}).success(function (data,status) {
if(status==200){
    alert('Successfully logged in');
    $location.path('/dashboard'); //You can use this if you are defined your states.
}
}).error(function (data,status) {
    if(status==403||status==403){ //Based on what error code you are returning from API
     $location.path('/login');// if states are defined else
     $window.location.href = "https://www.google.com";
    }
});

Upvotes: 2

Nicolas Law-Dune
Nicolas Law-Dune

Reputation: 1703

Use a interceptor service in order to centralize all of your rejection request in the same service.

module.config(['$httpProvider', ($httpProvider: ng.IHttpProvider) => {
    $httpProvider.interceptors.push('errorService');
}]);


module.factory('errorService', ['$location', function($location) {  
   var errorService = {
       responseError: function(rejection) {
           if (rejection === '401') {
               $location.path('/login');
           }
       }
    };
    return errorService;
}]);

Upvotes: 3

Simanchal.panigrahi
Simanchal.panigrahi

Reputation: 86

Example :

  $http.post('/myapp/api/getData', data)
     .then(function (data) {
         if(data.ErrorCode==1)
        {
             $window.location.href="controllerName/actionName";
        }
     })

Upvotes: 3

gyc
gyc

Reputation: 4360

The $http.post is misguiding. So far the best answer is @Kliment's. Interceptors are the best way to manage what comes before and after http requests.

However, if your end goal is to prevent access to a page, you have to at least use a routing plugin (ngRoute, ui-router) because with the promise idea there will always be a delay between the http request and the response.

Depending on server response time you'll still see the page display for about a second or so.

With ui-router you simply configure a resolve method for each state you want to protect. It could look like this:

.state('protected',
{
    url : '/protected_page',
    templateUrl : 'secret.html',
    resolve: {
        loggedin: loggedin
    }
})

loggedin refers to a function you define that contains your $http.post call (or better yet a service)

function loggedin($timeout, $q, $location, loginService) {
    loginService.then(function(data) {
        if(data.status == 401) {
            //$timeout(function() { $location.path('/login'); });
            return $q.reject();
        } else {
            return $q.when();
        }
    });
}

Here this particular service returns a 401 status but you can return anything.

The state will not be resolved (and the page not displayed) until it's accepted or rejected.

You can redirect directly from there if you want, although it's not very elegant. ui-router gives you another option with default redirection:

if (tokenIsValid()) 
    $urlRouterProvider.otherwise("/home");
else
    $urlRouterProvider.otherwise("/login");

With otherwise you tell ui-router to go to certain urls if no state exists for a particular request or if a resolve has been rejected.

On another subject, your http request is badly written.

.success and .error are deprecated and you don't need to create a promise ($q) over an $http request that itself already returns a promise.

You have a good example in the documentation linked above.

Upvotes: 2

Kliment
Kliment

Reputation: 2270

The best way to catch global AuthenticationErrorin angular is with interceptor. This way you can monitor all request that are sent from angular and check for AuthenticationError.

$provide.factory('AuthErrorInterceptor', function($q, $location) {
  return {
   'responseError': function(rejection) {

        //check for auth error

        $location.path('/login');

        return $q.reject(rejection);
    }
  };
});

Upvotes: 3

Sreekanth
Sreekanth

Reputation: 3130

You could do a redirect to the page using $window.location.href, based on the error condition you have.

var app = angular.module("sampleApp", []);

app.controller("sampleController", [
  "$scope",
  '$window',
  'sampleService',
  function($scope, $window, sampleService) {
    sampleService.getData().then(function(result) {}, function(error) {
      if (error.statusCode === 400) {
        alert("Error");
        $window.location.href = "http://stackoverflow.com"
      }
    });
  }
]);
app.service("sampleService", function() {
  this.getData = function() {
    var promise = new Promise(function(resolve, reject) {
      setTimeout(function() {
        reject({
          statusCode: 400
        });
      }, 1000);
    });
    return promise;
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-App="sampleApp">
  <div ng-controller="sampleController">
  </div>
</div>

Upvotes: 3

Related Questions