I am struggling with angular here. What I learned is that factory and service functions of a module create only one instance of an object associating properties ( functions and variables) with it. And that that instance is available throughout the controllers of the application.
In my app I have created a service module userAngService
as follows:
var ser = angular.module('userAngService',[]);
ser.service('userAngService',['$cookies','$location','$http','$log','$rootScope',function($cookies,$location,$http,$log,$rootScope){
this.user = {};
$rootScope.username = {};
$rootScope.user = {};
/*this.loadUserData = function(username){
return $http({
method: 'GET',
url: 'http://localhost:7070/storyBoard/webapi/profiles/'+username
}).success(function(data){
user = data.data;
//return user;
});
};*/
this.login = function(val){
return $http({
method: 'GET',
url: 'http://localhost:7070/storyBoard/webapi/stories?username='+val.username+'&password='+val.password
}).then(function(data){
if(data.data==="Success"){
$rootScope.username = val.username;
$cookies.put("username", val.username);
$http({
method: 'GET',
url: 'http://localhost:7070/storyBoard/webapi/profiles/'+val.username
}).success(function(data){
console.log(data);
this.user = data;
console.log(this.user);
});
$location.path("/home");
}else{
window.alert('Wrong username or password');
}
});
};
this.logout = function(){
$rootScope.user.username = "";
$cookies.remove("username");
$location.path("/Diary");
};
this.addToShelf = function(wsPublish){
wsPublish.author = $rootScope.user.username;
return $http({
method: 'POST',
url:'http://localhost:7070/storyBoard/webapi/stories',
data: wsPublish
}).then(function(data){
this.user.stories.push(data.data);
});
};
}]);
It contains 3 functions and private variable this.user
and 2 rootScope variables $rootScope.username
& $rootScope.user
. Our concerned function is this.login()
function here.
Now,
To use this service module I created a module AllControllers
:
var app = angular.module('AllControllers',['userAngService']);
and I associated 2 controllers with it.
First controller:
app.controller('LoginFormController',['$cookies','$rootScope','$log','$scope','userAngService','userBean',function($cookies,$rootScope,$log,$scope,userAngService,userBean){
$scope.login = function(val){
userAngService.login(val);
};
$scope.logout = function(){
userAngService.logout();
};
$scope.publishGroup = function(obj){
userBean.publishGroup(obj);
};
}]);
*This controller is injected with dependency of userAngService
and it's login()
function delegates a call to login() function of userAngService
service
The login()
function in userAngService
changes its private variables properties. Which then I am trying to use in another controller and that's where all the problem is. When I am logging the returned promise
data in userAngService
itself, it is logging successfully but when I try to access in another controller, it just logs an empty object
Second Controller (from where accessing the service's private variables) :
app.controller('ReachController',['$cookies','$scope','$rootScope','userAngService',function($cookies,$scope,$rootScope,userAngService){
$scope.user = {};
$scope.username = {};
$scope.user = userAngService.user;
console.log(userAngService.user);
$scope.username = $cookies.get("username");
/*userAngService.loadUserData($scope.username).then(function(data){
$scope.user = data.data;
console.log($scope.user);
});*/
console.log($scope.user);
console.log($rootScope.user);
$scope.logout = function(){
userAngService.logout();
};
$scope.addToShelf = function(wsPublish){
userAngService.addToShelf(wsPublish);
};
}]);
Well an empty object can only mean that the object properties are defined to null and are not updated by login()
function of service. However, in userAndService
withing success
callback;
console.log(data);
this.user = data;
console.log(this.user);
these lines of code successfully log returned data, while in ReachController
or Second Controller 's lines;
$scope.user = userAngService.user;
...
console.log($scope.user);
logs this to console:
Object {}
There are no errors so code is right but then something wrong conceptually I guess. Please help!
if you want to return a data use factory instead of service.
Service always returns a methods with data.
console.log(data);
this.user = data;
console.log(this.user);
"this" object is for local scope of Success function. it will overridden service "this" object.
My guess is that the problem is in the same naming of service and parent module - userAngService
. Try renaming module to userAngServiceModule
. I would expect angular's DI to get confused whether you are referring to module or service when you add dependency to userAngService
.
The this
context inside a promise .then
handler is not the same as the this
context of a service.
app.service("myService", function($http) {
var myService = this;
this.data = {};
this.fetch = function(url) {
//return promise
return (
$http.get(url).then (function onFulfilled(response) {
//Won't work
//this.data = response.data;
//Instead use the binding
myService.data = response.data;
//Return data for chaining
return myService.data;
}).catch (function onRejected(response) {
console.log(response.status);
//throw to chain rejection
throw response;
});
);
};
});
The this
context in the onFulfilled
function is not the same as the this
context of the service. Instead bind the this
context of the service to a variable and use that variable in the onFulfilled
function of the promise .then
method.
Also be aware that this.data
variable of the service gets set in the future sometime after the XHR by the $http
service completes. To be sure the data is available, use the promise that the fetch
function returns.
var promise = myService.fetch(url);
promise.then (function onFulfilled(data) {
$scope.data = data;
}).catch( function onRejected(errorResponse) {
console.log(errorResponse.status);
});
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.