2

What I'm trying to build is a login service. I have written a factory that I need to be used by every controller. It's for checking whether user is logged in or not. But I'm getting this error:

Provider must return value from $get factory method

I'm very much new to Angular. Here is my index page:

<!DOCTYPE html>
<html ng-app="myApp">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Index Page</title>

        <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
        <script src="assets/lib/angular.js"></script>
        <script src="assets/lib/angular-route.js"></script>

        <script src="app/app.js"></script>
        <script src="app/AuthenticationService.js"></script>
    </head>
    <body>
        <div ng-view></div>
    </body>
</html>

app.js file:

( function () {

    angular.module('myApp', [
        'ngRoute',
        'ngAnimate',
        'myApp.login',
        'myApp.home',
        'myApp.AuthenticationService'
    ])  
    .config(['$routeProvider', function($routeProvider) {
        $routeProvider
        .when('/login', {
            controller: 'LoginController',
            templateUrl: 'loginView.html',
            controllerAs: 'vm'
        })
        .when('/home', {
            controller: 'HomeController',
            templateUrl: 'HomeView.html',
            controllerAs: 'vm'
        })
        .otherwise({
            redirectTo: '/login'
        });
    }]);    
})();

And this is the factory that I set up:

    (function() {

    angular
    .module('myApp.AuthenticationService', [])

    .factory('AuthService', ["$http", "$location", function($http, $location){
        var vm = this;
        vm.checkToken = function(token){
            var data = {token: token};
            $http.post("endpoints/checkToken.php", data).success(function(response){
                if (response === "unauthorized"){
                    console.log("Logged out");
                    $location.path('/login');
                } else {
                    console.log("Logged In");
                    return response;
                }
            }).error(function(error){
                $location.path('/login');
            })

        }

    }]);

    })();

And this is how I inject it in a controller:

(function() {

    angular
        .module('myApp.home', [])

        .controller('HomeController', function($routeParams,AuthService) {
                var vm = this;      

                //If user is not logged in
                var token;
                if (localStorage['token']){
                token = JSON.parse(localStorage['token']);
                } else {
                token = "something stupid";
                }
                AuthService.checkToken(token);

                $scope.logout = function(){
                    var data = {
                        token: token
                    }

                    $http.post('endpoints/logout.php', data).success(function(response){
                        console.log(response)
                        localStorage.clear();
                        $state.go("login");
                    }).error(function(error){
                        console.error(error);
                    })
                }

        });

})();

Can anyone point out the mistake I made? Thanks in advance.

version 2
  • 999
  • 2
  • 13
  • 29

3 Answers3

4
 .factory('AuthService', ["$http", "$location", function($http, $location){
        var vm = this;
        vm.checkToken = function(token){
            var data = {token: token};
            $http.post("endpoints/checkToken.php", data).success(function(response){
                if (response === "unauthorized"){
                    console.log("Logged out");
                    $location.path('/login');
                } else {
                    console.log("Logged In");
                    return response;
                }
            }).error(function(error){
                $location.path('/login');
            })

        }
       return vm;
    }]);

Angular factory should return an object to be consumed by the controller.

Sajal
  • 4,199
  • 1
  • 16
  • 37
  • `vm` (View Model) is used in a controller and not in a Service. Also, I think is better to use an `{}` (new object) instead of `this`, because the factory it is not gonna be instantiated and the `this` has the reference of something else that is not the expected. – Henrique Limas May 17 '16 at 11:58
0
(function() {

angular
.module('myApp.AuthenticationService', [])

.factory('AuthService', ["$http", "$location", function($http, $location){
    var vm = {};
    vm.checkToken = function(token){
        var data = {token: token};
        $http.post("endpoints/checkToken.php", data).success(function(response){
            if (response === "unauthorized"){
                console.log("Logged out");
                $location.path('/login');
            } else {
                console.log("Logged In");
                return response;
            }
        }).error(function(error){
            $location.path('/login');
        })

    }

    return vm;
}]);

})();

or below is the better way to create factory:

(function() {

angular
.module('myApp.AuthenticationService', [])

.factory('AuthService', ["$http", "$location", function($http, $location){

    var vm = {
        checkToken: checkToken
    };

    function checkToken(token){
        var data = {token: token};
        $http.post("endpoints/checkToken.php", data).success(function(response){
            if (response === "unauthorized"){
                console.log("Logged out");
                $location.path('/login');
            } else {
                console.log("Logged In");
                return response;
            }
        }).error(function(error){
            $location.path('/login');
        })

    }

    return vm;
}]);

})();
Rahul Nikate
  • 5,716
  • 5
  • 35
  • 50
Suneet Bansal
  • 2,267
  • 1
  • 12
  • 17
0

The problem here is because you are not returning an object in the factory function. In your case, instead of using .factory(), you need to use .service(). This is because your are using a constructor function (using this inside the function). If you want to use factory you can do as follow:

.factory('AuthService', ["$http", "$location", function($http, $location){
    var service = {
       checkToken: function() {...}
    };

    return service;
}])

You can follow the John Papa Style Guide and prefer use factory instead of service.

Henrique Limas
  • 287
  • 1
  • 10