Fabrizio Franzè
Fabrizio Franzè

Reputation: 45

AngularJS Time to load factory

Hi I've create an application angular, I would login user with a call http get to WS Java. I use a view in angular, to pass parameters between views i use a factory.

My code: I create angular module

angular.module('contactMgr',['ngRoute'])
.controller('AppCtrl',['$scope',function ($scope){}])

.config(['$routeProvider','$locationProvider',
                 function($routeProvider,$locationProvider){

            $routeProvider.when('/',{
              controller: 'homePageCtrl',
              templateUrl: 'assets/partials/homePage.html'
            })
            .when('/login',{
              controller: 'loginCtrl',
              templateUrl: 'assets/partials/login.html'
            })
            .when('/loginError',{
              controller: 'loginErrorCtrl',
              templateUrl: 'assets/partials/loginError.html'
            });
}])

Then add controller for login that call WS to execute login. If the WS response ID i call method load in a factory to load the user, and finally i redirect to home page

.controller('loginCtrl',['$scope','$http','$location','UserLogged',
                         function($scope,$http,$location,UserLogged){
   $scope.loginFunction = function(){
      $http({method: 'GET',
             url: 'http://localhost:8080/TaskManagerWS/login/'+$scope.lg_email+':'+$scope.lg_password
      }).then(function success(data,status,xhr){
                $scope.idUser = data.data;
                if($scope.idUser!=0){
                  UserLogged.load($scope.idUser);
                  $location.path("/");
                } 
                else{ $location.path("/loginError"); }
                },
              function error(data,status,xhr){ alert("Error on call function!"); }
            );
   };
}])

my factory to load user

.factory('UserLogged',['$http',function($http){
  var userLogged;

  return{
  load: function(id){
     $http({
          method: 'GET',
          url: 'http://localhost:8080/TaskManagerWS/user/id='+id
          }).then(function success(data,status,xhr){
                  userLogged = data.data;
                },
                function error(data,status,xhr){
                  window.alert("Error on call function!");
                }
              );
  },
  get: function(){
         return userLogged;
  }
 }
}])

And finally my controller for home page

.controller('homePageCtrl',['$scope','UserLogged',function($scope,UserLogged){
     $scope.user = UserLogged.get();
}])

All call working fine but, when i redirect to home page I don't see the result.

My home page are only tag "h1" with {{user.name}}.

But if i navigation navbar and change view and then i return to home page the title see.

Why this behavior? I would load immediately factory.

I think that angular before load page and then load factory. There is any instruction to load before factory and then page?

I try to put in the var userLogged on factory a static string and then work fine, the title load immediately. Maybe the time problem are in the $http call.

There is any method to reload view after the response of $http service?

Thanks

SOLVED:

Thanks @Matthew Cawley

I change my loginCTRL and add

UserLogged.loadCall($scope.idUser).then(function success(data,status,xhr){
                        UserLogged.loadFactory(data.data);
                        $location.path("/");
                      },
                      function error(data,status,xhr){
                        window.alert("Error on call function!");
                      }
                    );
            }

and then i change factory to return $http in the method load and finally i add method to loadFactory to load userLogged.

There is a solution that i don't really like, but seems is the only.

Upvotes: 1

Views: 729

Answers (1)

Matthew Cawley
Matthew Cawley

Reputation: 2818

It looks like you're redirecting to the home page to soon, i.e. before the UserLogged service has finished loading and set it's ownuserLogged variable to the data returned by the $http call.

This means that when you call $scope.user = UserLogged.get(); in your homePageCtrl it goes straight to the service's get method and returns nothing (because at this point userLogged hasn't been set).

Then, moments later (without really noticing it)... the $http call completes and the userLogged variable becomes set with the results but it's too late.

Solution 1: Return a promise to use in the controller

Return the promise created by the $http service by adding the return keyword:

load: function(id){
   return $http({
      method: 'GET',
      url: 'http://localhost:8080/TaskManagerWS/user/id='+id
   })

and then in your loginCtrl, change:

UserLogged.load($scope.idUser);
$location.path("/");

to:

UserLogged.load($scope.idUser)
    .then(function(){
         $location.path("/");
    });

This way you'll only get redirected once the UserLogged.load() method has carried out it's work.

Solution 2: Pass a callback function into the service (or factory).

Create a function in loginCtrl that does a redirect:

var redirectToHome = function(){
    $location.path("/");
}

Then add an extra callback parameter to the service's load() function, and execute that callback function when the promise is resolved in the service (after userLogged has been set):

load: function(id, callback) { // <---- Add extra "callback" parameter
    $http({
        method: 'GET',
        url: 'http://localhost:8080/TaskManagerWS/user/id='+id
    }).then(function success(data,status,xhr){
        userLogged = data.data;
        callback(); // <---- Execute the callback function (whatever it contains)
    },function error(data,status,xhr){
        window.alert("Error on call function!");
    });   
}

Then in the loginCtrl when you call services login function, do so by passing in a reference to the redirectToHome function as the callback as follows:

UserLogged.load($scope.idUser, redirectToHome); // <--- redirectToHome becomes the callback.

Upvotes: 1

Related Questions