3

So this is my service that I use to fetch user details.

angular.module('app')
.factory('userDetailService', function($http) {
    var userData = {};

    function getUserDetails(userId) {
        if (userId) {
            return $http.get("/users/" + userId).success(function(data) {
                angular.copy(data[0], userData);
            });
        }
    }
    return {
        userData: userData,
        getUserDetails: getUserDetails
    }
})

Now in Controller 1 that uses this service, I have this bit of code which works fine as I get the relevant data.

$scope.getUserId = function(userId) {
        if (userId) {
            $scope.userData = userDetailService.userData;
            userDetailService.getUserDetails(userId).success(function() {
                console.log($scope.userData); //Prints valid user data
            });
        }
 };

After this function executes in Controller 1, I try to do the following in Controller 2:

$scope.userData = userDetailService.userData;
console.log($scope.userData); //Prints null

But $scope.userData is null. Isn't the whole purpose of using a service to share data between controllers? Since I have already set the value of userData in Controller 1, shouldn't I be able to access it in Controller 2?

Weirdly enough, the modal dialog which is the template for Controller 2 is able to access data in the form of {{userData.first_name}} or {{userData.last_name}}. If this works, why is $scope.userData null? What am I missing?

Edit:

Template 1:

<div id="myModal" ng-controller="Controller 1">
<modal-configure-user></modal-configure-user>
    <a data-toggle="modal" data-target="#configureUserModal" href="#" ng-click="getUserId(user.id)" data-id="user.id">{{user.first_name + ' ' +user.last_name}}</a>
</div>

Template 2:

<div ng-controller="Controller 2"  id="configureUserModal">
</div>

Both are modal dialog windows.

4
  • Can you explain a bit more about the connection between sctrl1 and 2? inheritance? diffrent views? diffrent routes? when does 1 executed and when is 2? Commented Dec 17, 2014 at 10:43
  • @BenDiamant I've put that in as well. Commented Dec 17, 2014 at 10:47
  • Please try console.log(userDetailService.userData) in both controller. service instance will be unique everytime you accessed from any controller. also ensure that service has loadded data before it logs it. Commented Dec 17, 2014 at 10:47
  • @JenishRabadiya console.log(userDetailService.userData) didn't work as well. Commented Dec 17, 2014 at 10:51

1 Answer 1

2

Your approach is not very reliable, since you can't be 100% sure that data has already loaded when you try to access it in the second controller. Instead of assigning user data to variable always invoke getUserDetails method, which returns a promise. Then you just need to cache loaded data to avoid duplicated requests.

angular.module('app')
.factory('userDetailService', function($q, $http) {

    var userData;

    function getUserDetails(userId) {
        if (userId) {
            return userData ? $q.when(userData) : $http.get("/users/" + userId).success(function(data) {
                userData = data;
                return userData;
            });
        }
    }

    return {
        getUserDetails: getUserDetails
    }
});

Wrapping userData into $q.when creates a promise object, which resolves immediately. This is what you need, because service API is now consistent - you always deal with promises.

The usage in both controller then would be:

userDetailService.getUserDetails(userId).then(function(data) {
    $scope.userData = data;
});
Sign up to request clarification or add additional context in comments.

8 Comments

Thanks for this! So let's say I do $scope.userData = userDetailService.getUserDetails(userId); in Controller 1. Now how would I access this userData in Controller 2 without passing in the ID and making a request again?
More specifically, how do I "cache loaded data to avoid duplicated requests" as you said?
See the answer, I added example.
If I do this once in Controller 1, then won't it make another request when I call it in Controller 2? What if I only want to pass the userId in Controller 1 and I just want to fetch the userData for that userId in Controller 2?
If data has loaded once in some of your controllers, then it will be cached and userDetailService.getUserDetails(userId) will resolve immediately.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.