JohnDizzle
JohnDizzle

Reputation: 1338

AngularJS service call from controller doesn´t work

I want to call a service from a controller to login a user. In order to test the general concept the services at this point should just return a JSON-object with some mock data.

If I press the login button, I receive an error message like this:

Error: loginService.loginTest(...).then is not a function
$scope.login@http://localhost/Clickstar/app/controller/loginController.js:15:3
Wa.prototype.functionCall/<@http://ajax.googleapis.com/ajax/libs/angularjs/1.2.6/angular.min.js:162:24
Mc[c]</<.compile/</</<@http://ajax.googleapis.com/ajax/libs/angularjs/1.2.6/angular.min.js:178:390
zd/this.$get</h.prototype.$eval@http://ajax.googleapis.com/ajax/libs/angularjs/1.2.6/angular.min.js:101:141
zd/this.$get</h.prototype.$apply@http://ajax.googleapis.com/ajax/libs/angularjs/1.2.6/angular.min.js:101:418
Mc[c]</<.compile/</<@http://ajax.googleapis.com/ajax/libs/angularjs/1.2.6/angular.min.js:178:370
Xc/c/<@http://ajax.googleapis.com/ajax/libs/angularjs/1.2.6/angular.min.js:27:145
q@http://ajax.googleapis.com/ajax/libs/angularjs/1.2.6/angular.min.js:7:378
Xc/c@http://ajax.googleapis.com/ajax/libs/angularjs/1.2.6/angular.min.js:27:129
 angular.min.js:84:35

Here is my code

login.html

<div>   

    <div>
      <form method="post" ng-submit="login()">
            <input name="username" type="text" ng-model="username" placeholder="username"><br>
            <input name="password" type="password" ng-model="password" placeholder="password"><br>
            <input type="submit" value="Login" class="center-button">
        </form>
    </div>

    <div ng-show="Login.success">
            Username: {{Login.loginUsername}} <br>
            Password: {{Login.loginPassword}} <br>
            UserID: {{Login.usernID}} <br>


    </div>  


</div>

loginService.js

app.service('loginService', function($http, $q) {


    this.loginTest = function(username, password)
    {

        var dummyData = {   "username" : username,
                            "password" : password,
                            "userID" : 007,
                            "loginStatus" : 1
        };

        return dummyData;

    };

    return this;

});

loginController.js

app.controller('loginController', function ($scope, loginService) {   

    var vm = this;
    vm.loginUsername = null;
    vm.loginPassword = null;
    vm.usernID = null;
    vm.success = null;


    $scope.login = function(){
        vm.loginUsername = $scope.username;
        vm.loginPassword = $scope.password;


        loginService.loginTest($scope.username, $scope.password)
        .then(function(dummyData){

            vm.loginUsername = dummyData.username;
            vm.loginPassword = dummyData.password;
            vm.usernID = dummyData.userID;

            if(dummyData.loginStatus == 1){
                vm.success = true;
            }
            else{
                vm.success = false;
            }
        })

    };
});

So what is the problem with my code and how can I fix it?

Upvotes: 0

Views: 41

Answers (3)

Joey Ciechanowicz
Joey Ciechanowicz

Reputation: 3663

The problem is that your mock login server is not returning a promise, which you are expecting within your controller.

You can change your loginTest method to instead return a promise by doing:

return $q(function(resolve, reject) {
  resolve(dummyData);
});

I would like to point out that your login service is returning the username and password which seems unnecessary, you should really be making a request to the server which would inform you whether or not the username/password was valid. You could mock a service that does this as follows:

app.service('loginService', function($http, $q) {

  var dummyData = {
    "username": username,
    "password": password,
    "userID": 007,
    "loginStatus": 1
  };

  this.loginTest = function(username, password) {
    return $q(function(resolve, reject) {
      if (username === dummyData.username && password === dummyData.password) {
        resolve({
          userId: dummyData.userID,
          loginStatus: dummyData.loginStatus
        });
      } else {
        reject("Incorrect username or password");
      }
    });
  };

  return this;

});

Note - If no es6 support

If you are deploying this to browsers that don't support ES6 then you need to use the defered API instead.

var deferred = $q.defer();
deferred.resolve(someData);
return deferred.promise;

is synonymous to

return $q(function(resolve, reject) { resolve(someData); }

Upvotes: 2

Vineet Desai
Vineet Desai

Reputation: 932

You have not associated controller to your form. The form tag should be
<form method="post" ng-submit="login()" ng-controller="loginController">
Alternatively you can also associate the controller to the div tag that contains the form.
Refer the AngularJS documentation here

Upvotes: 0

Satpal
Satpal

Reputation: 133433

You are returning JSON object where as it expects a promise from loginService.

Change the code the loginTest as

app.service('loginService', function($http, $q) {
    this.loginTest = function(username, password) {
        var dummyData = {
            "username": username,
            "password": password,
            "userID": 007,
            "loginStatus": 1
        };

        var deferred = $q.defer();
        deferred.resolve(dummyData);
        return deferred.promise;
    };
    return this;
});

Upvotes: 1

Related Questions