AngularJS 'Cannot read property 'then' of undefined'

19,494

Solution 1

This is more of a misuse of promises issue.

You might want to first take a look of how promises work:

From your service code:

login: function(username, password){
  var session;
  $http.post('../server/php/auth/auth.php', {
    username: username,
    password: password
  })
  .then(function(res){
    session = res;
  });
  return session;
}

When login(username, password) is called, session is still undefined upon returning.

This is because $http.post() is an asynchronous function, the .then() clause does not get executed immediately.

As pointed out by Snixtor's answer, you should "return the return value of $http.post()":

login: function(username, password){
  return $http.post('../server/php/auth/auth.php', {
    username: username,
    password: password
  });
}

Then referring to your controller's logIn method:

$scope.logIn = function(){
  loginService.login($scope.username, $scope.password).then(function(response){
    // response === 'session' 
  }, function(res){

  });
};

the response parameter from loginService.login().then() is exactly the value of your intended session variable from your previous implementation.

Solution 2

You're returning an unassigned variable named "session". So what you are doing here in your logged in method is returning undefined. Undefined does not have a method called then.

login: function(username, password){
      var session;
      $http.post('../server/php/auth/auth.php', {
        username: username,
        password: password
      })
      .then(function(res){
        session = res;
      });
      return session;
    },

My guess is you actually want to return the $http.post method, which in turn returns a promise. That way you can use the session in the controller?

Solution 3

Your service function login is failing to return the promise created by the call to $http.post. Instead, you need this:

login: function(username, password){
  return $http.post('../server/php/auth/auth.php', {
    username: username,
    password: password
  });
}

Note too that I've removed the session variable from the function. It's the then function in your controller that needs to be dealing with the response.

Your isLogged and logOut functions look good already. Just repeat that pattern.

Share:
19,494
faserx
Author by

faserx

Updated on June 23, 2022

Comments

  • faserx
    faserx almost 2 years

    I've this problem, when I click on login button, the chrome console log this:

    angular.min.js:117 TypeError: Cannot read property 'then' of undefined at m.$scope.logIn (loginModuleController.js:11)

    Service:

    angular.module('loginModule')
    .factory('loginService', function($http){
      return{
        login: function(username, password){
          var session;
          $http.post('../server/php/auth/auth.php', {
            username: username,
            password: password
          })
          .then(function(res){
            session = res;
          });
          return session;
        },
        isLogged: function(){
          return $http.get('../angCMS/server/php/auth.php?is_logged=true');
        },
        logOut: function(){
          return $http.get('../angCMS/server/php/auth.php?logout=true');
        }
      };
    });
    

    controller:

    angular.module('loginModule')
    .controller('LoginCtrl', ['$scope', 'loginService', function($scope, loginService){
    
      $scope.auth = false;
    
      $scope.username;
      $scope.password;
      $scope.logIn = function(){
        loginService.login($scope.username, $scope.password).then(function(response){
    
        }, function(res){
    
        });
      };
    
      $scope.isLogged = function(){
        loginService.isLogged()
        .then(function(response){
          if(response){
            $scope.auth = true;
          }
        });
      };
    
      $scope.logOut = function(){
        loginService.logOut()
        .then(function(response){
          if(response){
            $scope.auth = false;
          }
        });
      };
    
    }]);
    

    and this is the html template:

    <div class="container" ng-if="auth==false">
      <div class="col-md-4 col-md-offset-4">
        <div class="row">
          <br/><h2 align="center">Login</h2>
        </div>
        <div class="well">
            <form class="form-horizontal">
            <fieldset>
              <div class="form-group">
                    <input type="text" class="form-control" placeholder="Username" ng-model="username" required>
              </div>
              <div class="form-group">
                    <input type="password"  class="form-control" placeholder="Password" ng-model="password" required>
              </div>
              <div class="form-group">
                    <button class="btn btn-md btn-primary btn-block" type="submit" ng-click="logIn()">Sign in</button>
              </div>
            </fieldset>
          </div>
        </form>
      </div>
    </div>
    

    PHP login method:

    public function login($user, $pass){
    
            $user = htmlspecialchars(trim($user));
            $pass = md5(htmlspecialchars(trim($pass)));
    
            $res = $this->DB->prepare("SELECT * FROM `admin` WHERE username = :user");
            if(!$res->execute(Array(":user"=>$user)))
                die(mysql_error());
    
            $row = $res->fetch(PDO::FETCH_ASSOC);
    
            if(!$row['password'] == $pass)
                die("Errore: password errata!");
    
            $_SESSION['logged'] = $row;
            array_push($session, $_SESSION['logged'], true);
    
            return $session;
        }