I'm struggling with using the value that I got from a 'get' in my controller.
This is my code in my controller
vm.user;
function onInit(){
loadUser(vm.queryParams.id[0]);
console.log(vm.user);
}
function loadUser(UserId) {
var defer = $q.defer();
User.get({ id: userId }).$promise.then(function (user) {
vm.user = user;
defer.resolve();
});
return defer.promise;
};
When I print the vm.user in the onInit() it is undefined. While when I look on the view where vm.user is called it just shows me the correct values of the user. So it's not known after the loadUser() in the controller but it is in my view.
I would like to first 'get' the user and then use it for further logic in the onInit(). How to retrieve the user properly so I can further use it and call its values in the onInit()?
You have to wait till the execution of loadUser() is finished so as the get the value of user.You can use the promise returned like this and do any calcualtions on it.
vm.user;
function onInit(){
var promise=loadUser(vm.queryParams.id[0]);
promise.then(function(response){
console.log(response);
});
}
function loadUser(UserId) {
var defer = $q.defer();
User.get({ id: userId }).$promise.then(function (user) {
vm.user = user;
defer.resolve(vm.user);
});
return defer.promise;
};
Immediately invoke your init function at the beginning of your controller and convert your loadUser function to a service since its a get action. Your service will return the user which you can then set.
(Declare at top of controller):
init();
function init(){
loadUserService.loadUser(UserId)
.then(function (user) {
vm.user = user;
defer.resolve();
})
}
Related
I created a form and onclick of the form i want to see the response from the server(nosejs). In Angular Controller Im calling the service. The response is visible when called from the service itself, but when called from the controller nothing shows up.
Controller:
MyApp.angular.controller("loginCtrl", function($scope, UserService){
$scope.name = "TestName";
$scope.check = function(user){
UserService.createUser(user, function(response){
$scope.userinfo = response;
console.log("FROM Ctrlr: " + response);
});
}
});
Service:
MyApp.angular.factory("UserService", function($http,$location){
var service = {
createUser: createUser
};
return service;
function createUser(user){
$http.post("/register", user).then(function(response){
console.log("FROM Srvc:" +response);
});
}
});
NodeJS:
app.post("/register", function(req, res){
var user = req.body;
res.json(user);
});
I can see the response logged to the console if I call it from the Service. But no response when called from the controller itself. Reason to include MyApp.angular.factory and MyApp.angular.controller is I have declared MyApp in another config file.
What am I doing wrong?
In order to get the response in your controller from the factory change your createUser func in your factory like this:
function createUser(user){
//notice the return here!!!
return $http.post("/register", user).then(function(response){
console.log("FROM Srvc:" +response);
return response.data; //notice the return here too!!!
});
}
You need to return the promise inside the function and inside the then return the result as well in order to get access to it from wherever you call the function.
Unlike node.js which uses callback-based APIs, the AngularJS framework uses promise-based APIs. Return the promise and use its .then method:
Controller
app.controller("loginCtrl", function($scope, UserService){
$scope.name = "TestName";
$scope.check = function(user){
//UserService.createUser(user, function(response){
//USE .then method
return UserService.createUser(user).then(function(data) {
$scope.userinfo = data;
console.log("FROM Ctrlr: " + data);
return data;
}).catch(function(errorResponse) {
console.log(errorResponse.status);
throw errorResponse;
});
}
});
Service
function createUser(user){
var promise = $http.post("/register", user).then(function(response){
var data = response.data;
console.log("FROM Srvc:" +data);
//RETURN data to chain
return data;
});
//RETURN promise
return promise;
}
Don't convert promise-based APIs to callback-type APIs. It's considered an anti-pattern.
See Why are Callbacks from Promise .then Methods an Anti-Pattern.
You need to add 1 more parameter, callback and return the response to the callback function
function createUser(user, callback){
$http.post("/register", user).then(function(response){
console.log("FROM Srvc:" +response);
callback(response); // return the response in the callback function
});
}
I have made two factory and calling first from second one, consuming second one factory in controller but instead of getting data as JSON, I'm getting data as $$State.
I'm new to angularJS tried many ways but not able to solve, please help.
app.factory('userDetails', ['APIService', '$q', function (APIService, $q) {
getDetails: function () {
var deferred = $q.defer();
var getFunc = function () {
APIService.doGetCall('Masters/employee/username/tarun')
.then(
function (data)
{
deferred.resolve(data);
},
function (data, status, headers, config)
{
deferred.reject('There was an error creating object'); })
return deferred.promise;
}
var a = getFunc();
return a;
}
}
vm.user = userDetails.getDetails();
console.log("user",vm.user);
response is as per below snippet
Response
You should be using .then function to get response there. Rather I'd say you don't need to create extra promise, its an anti-pattern. Where you could utilize the promise return by doGetCall method directly.
app.factory('userDetails', ['APIService', '$q', function(APIService, $q) {
getDetails: function() {
var getFunc = function() {
return APIService.doGetCall('Masters/employee/username/tarun');
}
var a = getFunc();
return a;
}
}]);
vm.user = userDetails.getDetails().then(function(response){
console.log(response.data);
vm.user = response.data;
console.log("user", vm.user);
}, function(error){
console.log(error)
}).catch(exceptionHandler);
userDetails.getDetails() returns a promise, Hence you need to use .then(onsuccess, onRejected)
userDetails.getDetails().then(function(data){
vm.user = data;
console.log("user",vm.user);
});
You've got the
return deferred.promise;
line inside the APIService.doGetCall function. It should be outside of it.
Im combining 2 promises but isnt working, in a service i have 2 methods, where the method "UserService.getAuthenticatedUser()" gets the current user information and than there is a "UserService.getAccountTypeData(idUser)", where gets the usertype information, but to get to the second method i need the userID, so basically first i call the "UserService.getAuthenticatedUser()", get the id, and than call "UserService.getAccountTypeData(idUser)", but isnt working.
function isAccount(accountName) {
UserService.getAuthenticatedUser()
.then(function (response) {
var userDetails = response.data;
});
UserService.getAccountTypeData(idUser)
.then(function (response) {
var userDetails = response.data;
return userDetails;
});
}
PS: I already injected the service...
You can chain your promises by returning values from your .then() functions.
function isAccount(accountName) {
return UserService.getAuthenticatedUser(accountName) // pass in accountName argument?
.then(function(response) {
var userDetails = response.data;
return userDetails.Id; // user id value
})
.then(UserService.getAccountTypeData) // userDetails.Id gets passed to getAccounttypeData method
.then(function(response) {
var userDetails = response.data;
return userDetails;
});
}
// usage
isAccount('AccountA').then(function(userDetails) {
// do something with userDetails
});
You're dealing with asynchronous calls, so when you call the .then() method, it's executing the function and wiring up the callback to an anonymous function passed as a parameter to then(). If the second is dependent on the first, you could nest them like this...
function isAccount(accountName) {
UserService.getAuthenticatedUser()
.then(function (response) {
var userDetails = response.data;
UserService.getAccountTypeData(idUser)
.then(function (response) {
var userDetails = response.data;
return userDetails;
});
});
}
I need to get localeData value print out side of below function.
I know how to print in side of function like what i did here.
I have tried this but didn't work.
$http.post(SERVER_URL + 'getLocaleData').success(function(localeData) {
console.log(localeData);
}).error(function(err) {
alert('warning', err.message);
});
//need to get that value here.
console.log(localeData);
EDIT
Actually i need to do is this
app.factory('customLoader', function($http, $q, SERVER_URL) {
return function(options) {
var deferred = $q.defer();
// do something with $http, $q and key to load localization files
$http.post(SERVER_URL + 'getLocaleData').success(function(localeData) {
//do something here to localData
}).error(function(err) {
alert('warning', err.message);
});
deferred.resolve(localeData);
return deferred.promise;
};
});
This is what i need. finally i need to send localeData.
You don't need to create & resolve a defer yourself. There is an easier way. (Also in the example you give, you resolve promise before the underlying ajax completed)
Angular.js $http service follows $q interface too! So you can write:
app.factory('customLoader', function($http, $q, SERVER_URL) {
return function(options) {
var promise = $http.post(SERVER_URL + 'getLocaleData')
.then(function(localeDataBag) {
var localeData = localeDataBag.data; // .data of 'then' equals to what .success returns.
modifiedLocaleData = localeData++; // do something here to localData
return modifiedLocaleData; // This is the new result
})
.catch(function(err) {
console.log(err);
return $q.reject(err); // This is the new result if something failed. Since we are chaining promises, we should keep failure state.
});
return promise;
};
});
You don't need $q to accomplish your objective:
app.factory('customLoader', ["$http", "SERVER_URL", function($http, SERVER_URL) {
return function(options) {
return $http.post(SERVER_URL + 'getLocaleData');
};
}]);
Because $http and all it's convenience methods actually return a promise. In this case, you can use this service as follows:
customLoader(options).success(function(localeData){
//do something here to localData
}).error(function(err){
alert('warning', err.message);
});
If you really must use $q, then this should do:
app.factory('customLoader', ["$http", "$q", "SERVER_URL", function($http, $q, SERVER_URL) {
return function(options) {
return $q(function(resolve, reject){
$http.post(SERVER_URL + 'getLocaleData').success(function(localeData) {
//do something here to localData
resolve(localeData); // ultimately you ought to resolve inside this function
}).error(function(err) {
alert('warning', err.message);
reject(localeData); // ultimately you ought to reject inside this function
});
});
};
}]);
JS is asynchronous, which basically means that your last console.log will be executed before your server returned any data. So you have to do it inside both your promises:
$http.post(SERVER_URL + 'getLocaleData').success(function(localeData) {
console.log(localeData);
}).error(function(err) {
console.log(err);
alert('warning', err.message); //Just in case you didn't know, this line supposes that your server returns a JSON object with a "message"-property
});
That way, your server-response will be console.log'ed both on success and failure.
Reference
Edit: If you really wanna do it the other way:
var response; //First, declare a variable in the parent scope.
$http.post(SERVER_URL + 'getLocaleData').success(function(localeData) {
response = localeData; //Assign the response data to the variable.
console.log(localeData);
}).error(function(err) {
alert('warning', err.message); //Just in case you didn't know, this line supposes that your server returns a JSON object with a "message"-property
});
console.log(response);
The example won't evaluate as you expect, though. The last console.log will just log undefined.
By following way you can access your server response outside factory in the controller:
app.factory('customLoader', function ($http, $q) {
return {
response: {},
getLocalData: function (param) {
var deferred = $q.defer();
$http.post(SERVER_URL + 'getLocaleData', param).
success(function (data, status, headers, config) {
deferred.resolve(data);
}).
error(function (data, status, headers, config) {
});
return deferred.promise;
}
}
});
app.controller('yourCtrl', function($scope,customLoader) {
$scope.GetLocaleData= function() {
customLoader.getLocalData({
Role: role,
Email_Id: $scope.Email,
Pwd: $scope.Password
}).then(function(localeData) {
$scope.Data = localeData;
});
}
});
localeData is limited to the scope of .success function. You cant get it outside unless you assign it some other variable.
var data = ""
$http.post(SERVER_URL + 'getLocaleData').success(function(localeData) {
data = localeData;
}).error(function(err) {
alert('warning', err.message);
});
//need to get that value here.
console.log(data);
But dont expect to get the desired value in data until you get the response back. $http.post is async
Take a look at promises to overcome such issues, because they are used all over the place, in angular world.
UPDATE:
As you have done in the edit, you may either use $q service like:
app.factory('customLoader', function($http, $q, SERVER_URL) {
return function(options) {
var deferred = $q.defer();
// do something with $http, $q and key to load localization files
$http.post(SERVER_URL + 'getLocaleData').success(function(localeData) {
//do something here to localData
}).error(function(err) {
alert('warning', err.message);
});
deferred.resolve(localeData);
return deferred.promise;
};
});
OR, you may simply return $http.post which itself returns a promise
app.factory('customLoader', function($http, $q, SERVER_URL) {
return function(options) {
return $http.post(SERVER_URL + 'getLocaleData');
};
});
In either way, you are returning a promise object and not just the actual response you get from server. The localeData can be accessed as follows:
customLoader().success(function(res){
console.log(res);
}).error(function(){
//show some error message
})
I am learning AngularJS and AJAX.I am trying to assign the data being returned by the success function to user. grantRole belongs to Auth service. The value of user as I currently have it is a promise. How do I assign the returned data on success to user?
$scope.grantRole = function(user) {
user = Auth.grantRole(user).then(
function success(data){
return data;
},
function error(err){
console.log(err);
}
);
grantRole: function(user,callback) {
var cb = callback || angular.noop;
var data = {id: user._id,controller:'role'};
return User.update({id: user._id,controller:'role'},data,
function(user) {
return cb(user);
}, function(err) {
return cb(err);
}).$promise;
};
The current value of user being a promise is correct. Once the promise gets resolved, it will be assigned to the data returned on success.
But you have to be careful when reassigning objects or arrays. See Service variable not updating in controller
E.g., don't do this: user = ...;
Rather, do this: angular.copy(newInfo, user) or this: user.email = ...
$scope.grantRole = function(user) {
Auth.grantRole(user).then(
function success(data){
angular.copy(data, user);
},
function error(err){
console.log(err);
}
);