0

I have an index page index.html with its controller indexController. I set some value($scope.ipAddress) in a factory in the indexController which is used by other controllers of the html inside ng-view.

When the page is loaded, the indexController is supposed to execute first, set a value in the factory and then that value is used by other controllers of pages inside ng-view.

But I think the other controllers are executed first before indexController and I get undefined for the value I set.

This is the indexController with factory:

        angular.module('tollApp')
.controller('indexController', function($scope,$http,$window,userDetailsFactory){
    $scope.usernameFromServer={};
    $scope.getUserDetails = function(){
        $http({
            method:'GET',
            url:'http://192.168.1.80:4000/getUserDetails'
            // url:'http://websitename.com/getUserDetails'
        })
        .then(function(response){

            // console.log(JSON.stringify(response));
            userDetailsFactory.setUserDetailsInFactory(response.data);
        $scope.usernameFromFactory = userDetailsFactory.getUserDetailsFromFactory().usernameFromSession;
        $scope.theIP = userDetailsFactory.getUserDetailsFromFactory().ipAddress;
            // $scope.usernameFromServer = userDetailsFactory.getUserDetailsFromFactory().username;
            // console.log(JSON.stringify($scope.usernameFromFactory)+"usernameFromFactory");
        })
    }
    $scope.logout = function(request,response){
        $http({
            method:'GET',
            url:'/logout'
        })
        .then(function(response){
            console.log(JSON.stringify(response));
            if(response.data=="logout"){
                // $window.location.href="http://websitename.comlogin";
                $window.location.href="http://192.168.1.80:4000/login";

            }
        })
    }
    console.log("indexController");
}).factory('userDetailsFactory',function(){
    var user = {};
    return {
        setUserDetailsInFactory : function(val){
            user.useridFromSession = val[0].UserID;
            user.usernameFromSession = val[0].UserName;
            user.userroleFromSession = val[0].UserRole;
            user.clientidFromSession = val[0].ClientID;
             user.ipAddress = "http://192.168.1.80:4000/";
            // user.ipAddress = "http://websitename.com/";
            // console.log("in set "+user.clientidFromSession);
        },
        getUserDetailsFromFactory : function(){
            return user;
        }
    };
})

The other controller where I use the value from factory:

$scope.ipForHttp = userDetailsFactory.getUserDetailsFromFactory().ipAddress;
console.log($scope.ipForHttp); //undefined
$scope.loading = false;
$scope.ClientID = userDetailsFactory.getUserDetailsFromFactory().clientidFromSession;
// $scope.dev={};

$scope.getDevice =function(){
    console.log($scope.ipForHttp); //undefined
    $scope.loading = true;

      $http({
        method : "GET",
        url : $scope.ipForHttp+"getDeviceDetailsReport"
      }).then(function mySucces(response) {

1 Answer 1

1

Take a look at your $scope.getUserDetails - you're using $http (docs) service to make an asycronous AJAX call to the back-end.

The callback function you supply in the .then() method of the returned object may be executed sometime in the future or may even not - depends on whether the call succeeds or fails. You must not expect it to behave syncronously, because it never will, even if the backend responds instantly.

That's why you can't expect to have the desired data in your other controllers and need to adjust your code accordingly, e.g.

// tells angular to execute watcher function on every $digest
$scope.$watch(function () {
    // watches the returned value of the service's method
    return userDetailsFactory.getUserDetailsFromFactory();
}, function (newVal) {
    // filtering out empty object
    if (!Object.keys(newVal).length) {
        return;
    }

    // the following code will be run when
    // userDetailsFactory.getUserDetailsFromFactory
    // returns some value
    // in our particular case - after getting
    // data from backend and setting it in
    // userDetailsFactory.setUserDetailsFromFactory

    $scope.loading = false;
    $scope.ipForHttp = newVal.ipAddress;
    $scope.ClientID = newVal.clientidFromSession;

    $scope.getDevice();
},
// tells angular to watch properties of the object too
true);

Optionally, if you need to execute that code only once when user details are set, do this

var unbindUserDetailsWatcher = $scope.$watch(function () {
    return userDetailsFactory.getUserDetailsFromFactory();
}, function (newVal) {
    if (!Object.keys(newVal).length) {
        return;
    }

    unbindUserDetailsWatcher();
    unbindUserDetailsWatcher = null;

    ...
});
Sign up to request clarification or add additional context in comments.

8 Comments

OP, there is a much better way of solving this task - using service and Promises ($q to be exact). You should take a look at the docs and examples and try to figure it out for yourself. Hint - the code that has mutliple dependants should be moved to the server. If you need any help with that - just comment and I'll show guide you to the correct solution.
It is the code that's supposed to go to the "other controller", I'll add comments to the code to make it easier for you to understand
The newValue is empty when I console.log(). It is {}. I have set a timeout on indeController(controller where I set the value in factory). so that it simulates my problem stated above which occurs only when I host. When I remove the timeout, I get all values.
also did you mean to type newValue instead of newVal in these lines above? $scope.ipForHttp = newVal.ipAddress; $scope.ClientID = newVal.clientidFromSession;
ow yeah, my bad. was sleepy when answering your question and made a few mistakes, gonna fix `em now
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.