Setting and getting data value from service in Angular JS
So this is my service that I am using to get 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 that works great when I receive 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 running this function in Controller 1
I will try to do the following in Controller 2
:
$scope.userData = userDetailService.userData;
console.log($scope.userData); //Prints null
But $scope.userData
it is null. Isn't that the purpose of using a data exchange service between controllers? Since I've already set the value userData
to Controller 1
, shouldn't I be able to access it in Controller 2
?
Oddly enough, a modal dialog that is a template for Controller 2
can access data in a form {{userData.first_name}}
or {{userData.last_name}}
. If this works, why $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 boxes.
source to share
Your approach is not very reliable as you cannot be 100% sure that the data has already been loaded when you try to access it in a second controller. Instead of assigning custom data to a variable, always call a method getUserDetails
that returns a promise. Then you just need to cache the loaded data to avoid duplicate 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
}
});
The wrapper userData
in $q.when
creates a promise object that resolves immediately. This is what you want as the service API is now consistent - you are always dealing with promises.
Usage in both controllers would be as follows:
userDetailService.getUserDetails(userId).then(function(data) {
$scope.userData = data;
});
source to share