0

I try to handle the success/error handling from the service in the controller.

I have tried this :

Service :

.factory('AuthenticationService',
['Base64', '$http', '$cookieStore', '$rootScope',
function (Base64, $http, $cookieStore, $rootScope) {
    var service = {};

    service.Login = function (username, password, callback) {

        var authdata = Base64.encode(username + ':' + password);

        $rootScope.globals = {
            currentUser: {
                username: username,
                authdata: authdata
            }
        };

        $http.defaults.headers.common['Authorization'] = 'Basic ' + authdata; 
        $cookieStore.put('globals', $rootScope.globals);

        $http.post('http://localhost:8080/v1/login', { username: username, password: password })
            .success(function (response) {
                callback(response);
            });
    };

    service.ClearCredentials = function () {
        $rootScope.globals = {};
        $cookieStore.remove('globals');
        $http.defaults.headers.common.Authorization = 'Basic ';
    };

    return service;
}])

and the controller :

.controller('LoginController',
['$scope', '$rootScope', '$location', 'AuthenticationService',
function ($scope, $rootScope, $location, AuthenticationService) {
    // reset login status
    AuthenticationService.ClearCredentials();

    $scope.login = function () {
        $scope.dataLoading = true;
        AuthenticationService.Login($scope.username, $scope.password, function (response) {
            if(response.success) {
                $location.path('/');
            } else {
                $scope.error= response.message;
                $scope.dataLoading = false;
            }   
        });
    };
}]);

If I try with an alert, it only shows in the service but not in the controller.

Jonny C
  • 1,943
  • 3
  • 20
  • 36
Kai
  • 79
  • 1
  • 3
  • 12

3 Answers3

0

Try using this

.factory('AuthenticationService',
['Base64', '$http', '$cookieStore', '$rootScope',
function (Base64, $http, $cookieStore, $rootScope) {
    var service = {};

    this.Login = function (username, password) {

        var authdata = Base64.encode(username + ':' + password);

        $rootScope.globals = {
            currentUser: {
                username: username,
                authdata: authdata
            }
        };

        $http.defaults.headers.common['Authorization'] = 'Basic ' + authdata; 
        $cookieStore.put('globals', $rootScope.globals);

        $http.post('http://localhost:8080/v1/login', { username: username, password: password })
            .success(function (response) {
                return response;
            });
    };

    this.ClearCredentials = function () {
        $rootScope.globals = {};
        $cookieStore.remove('globals');
        $http.defaults.headers.common.Authorization = 'Basic ';
    };
}])

Controller

.controller('LoginController',
['$scope', '$rootScope', '$location', 'AuthenticationService',
function ($scope, $rootScope, $location, AuthenticationService) {
    // reset login status
    AuthenticationService.ClearCredentials();

    $scope.login = function () {
        $scope.dataLoading = true;
       var response = AuthenticationService.Login($scope.username, $scope.password);
        if(response.success) {
                $location.path('/');
            } else {
                $scope.error= response.message;
                $scope.dataLoading = false;
            } 
    };
}]);
Sujithrao
  • 789
  • 3
  • 12
  • 27
0

Using promises :

.factory('AuthenticationService',
['Base64', '$http', '$cookieStore', '$rootScope', '$q', 
function (Base64, $http, $cookieStore, $rootScope, $q) {
    var service = {};

    service.Login = function (username, password, callback) {

        var deferred = $q.defer();

        var authdata = Base64.encode(username + ':' + password);

        $rootScope.globals = {
            currentUser: {
                username: username,
                authdata: authdata
            }
        };

        $http.defaults.headers.common['Authorization'] = 'Basic ' + authdata; 
        $cookieStore.put('globals', $rootScope.globals);

        $http.post('http://localhost:8080/v1/login', { username: username, password: password })
            .then(function (response) {
                deferred.resolve(response);
            }, function(error) {
                deferred.reject(error);
            });

        return deferred.promise;
    };

    service.ClearCredentials = function () {
        $rootScope.globals = {};
        $cookieStore.remove('globals');
        $http.defaults.headers.common.Authorization = 'Basic ';
    };

    return service;
}])

And your controller

.controller('LoginController',
['$scope', '$rootScope', '$location', 'AuthenticationService',
function ($scope, $rootScope, $location, AuthenticationService) {
    // reset login status
    AuthenticationService.ClearCredentials();

    $scope.login = function () {
        $scope.dataLoading = true;
        AuthenticationService.Login($scope.username, $scope.password)
            .then(function(success) {
                $location.path('/');
            }, function(error) {
                $scope.error= response.message;
                $scope.dataLoading = false;
            });
    };
}]);
  • "response is not defined" -.-, i have thinking about a promise too, but i dont know how i do it – Kai Nov 23 '16 at 14:53
  • Can you do a `console.log(response)` in your `$http.post` ? Because it's a valid code (I think), but you need to send back data ! –  Nov 23 '16 at 14:55
  • my fault ! its fine, its working ( i had the response on the function (error) .. thank you very much ! – Kai Nov 23 '16 at 15:02
  • you know how i can handle the error and success better than alert ? – Kai Nov 23 '16 at 15:09
  • What do you mean ? And don't forget to put your post as resolved –  Nov 23 '16 at 15:11
  • instead of alert if a error happen, a text under the login button or something – Kai Nov 23 '16 at 15:26
  • oh yeah, just replace your `alert` with a `$scope.errorMessage`, and in your form, under the input, `{{errorMessage}}`. It goes very well with Angular Material, which gives pretty error messages ! –  Nov 23 '16 at 15:28
  • The code can be simplified to avoid a [Q defer Anti-Pattern](http://stackoverflow.com/questions/30750207/is-this-a-deferred-antipattern). For more info, see [this SO answer](http://stackoverflow.com/a/40772648/5535245) – georgeawg Nov 23 '16 at 19:29
  • Actually, I want to thank you @georgeawg, I didn't know that ! I learned to return http calls like that, and never thought about looking for more information. Thank you ! I just have a question, what are the promises used for then ? –  Nov 24 '16 at 08:21
  • *The purpose of the promise object is to allow for interested parties to get access to the result of the deferred task when it completes.* -- [AngularJS $q Service API Reference -- The Promise API](https://docs.angularjs.org/api/ng/service/$q#the-promise-api). For more information, see [JavaScript Promises/A+ Spec](https://promisesaplus.com/). – georgeawg Nov 24 '16 at 17:25
  • I understood that, but the only asynchronous methods that comes to my mind are the http calls. is there another reason to use promises ? –  Nov 25 '16 at 09:01
0

There is no need to manufacture a promise with $q.defer() as the $http service already returns a promise. Avoid this Q Defer Anti-Pattern.

//AVOID this $q.defer ANTI-PATTERN 
var deferred = $q.defer();

$http.post('http://localhost:8080/v1/login', { username: username, password: password })
    .then(function (response) {
        deferred.resolve(response);
    }, function(error) {
        deferred.reject(error);
    });

return deferred.promise;

Instead simply use the promise that the $http service returns:

//INSTEAD return promise from $http

var promise = $http.post('http://localhost:8080/v1/login', { username: username, password: password });

return promise;
Community
  • 1
  • 1
georgeawg
  • 48,608
  • 13
  • 72
  • 95