I am trying to create a factory that makes an ajax request to some API and then returns an object of data. My code is:
app.factory('Test', function($http, $q) {
var data = {response:{}};
var getMessages = function() {
$http.get('https://someapi.com').then(
function(jsonAPI) {
var dataObj = {};
var messages = [];
$.each(jsonAPI.data.data, function(x, data) {
dataObj[x] = data;
$.each(jsonAPI.data.included, function(y, included) {
if(data.relationships.sender.data.id == included.id) {
dataObj[x].sender = included;
}
});
messages.push(dataObj[x]);
});
data.response = messages;
},
function(errorResponse) {
// todo handle error.
}
);
};
getMessages();
return {
data
};
});
However when I try to remove the 'response' attribute from the data object that is created and have data = messages instead of data.response = messages the data object is not getting filled. If I keep the response attribute then in my controller when I try to console.log(Test.data['response']) I get an empty object. console.log(Test.data) returns a valid object though. What am I missing here?
If you want to keep data stored in factory you can store the promise returned by $http and have that promise resolve with the stored data.
app.factory('Test', function($http, $q) {
var data = null, dataPromise = null;
function getMessages() {
if (!dataPromise) {
dataPromise = $http.get('https://someapi.com').then(
function (jsonAPI) {
var dataObj = {};
var messages = [];
$.each(jsonAPI.data.data, function (x, data) {
dataObj[x] = data;
$.each(jsonAPI.data.included, function (y, included) {
if (data.relationships.sender.data.id == included.id) {
dataObj[x].sender = included;
}
});
messages.push(dataObj[x]);
});
data = messages;
return data;
},
function (errorResponse) {
// todo handle error.
}
);
}
return dataPromise
}
return {
getMessages : getMessages
};
});
then in any controller or directive or resolve:
Test.getMessages().then(function(messages){
$scope.messages = messages;
});
Related
can someone help me with this code? I have problem with return value, function in controller return only
var products = {"id": 3};
I want to collect value from http.get, can someone tell me how to do that??
Controller:
$scope.product = {};
$scope.init = function () {
$scope.loadProducts()
}
$scope.loadProducts = function () {
// $http.get("/products/list").then(function (resp) {
// $scope.products = resp.data;
// })
$scope.products = getListProducts.loadProducts();
}
Service
var myServices = angular.module('myServices', []);
myServices.service('getListProducts', ['$http', function ($http) {
var products = {"id": 3};
this.loadProducts = function () {
$http.get("/products/list").then(function (resp) {
products = resp.data;
})
return products;
}
}]);
you are returning products before http success , instead use promises and resolve when http success
$scope.product = {};
$scope.init = function () {
$scope.loadProducts()
}
$scope.loadProducts = function () {
// $http.get("/products/list").then(function (resp) {
// $scope.products = resp.data;
// })
$scope.productPromise = getListProducts.loadProducts();
productPromise..then(function (resp) {
$scope.products = resp.data;
});
}
Service
var myServices = angular.module('myServices', []);
myServices.service('getListProducts', ['$http', function ($http) {
var products = {"id": 3};
this.loadProducts = function () {
return $http.get("/products/list");
}
}]);
Make use of promises to enforce serialization of your async code.
Refactor your service method as:
this.loadProducts = function () {
var getProducts = new Promise(function(resolve,reject){
$http.get("/products/list").then(function (resp) {
resolve(resp.data);
})
});
return getProducts;
};
And your Controller method as:
getListProducts.loadProducts().then(function(data){
//success callback
$scope.products = data;
});
You can provide the error callbacks as well.
Hope this helps !
You should use promises to return values from your service.
You can use $q in your service. It would help functions to run asynchronously.
myServices.service('getListProducts', ['$http','$q', function ($http,$q) {
var products = {"id": 3};
this.loadProducts = function () {
var deferred = $q.defer();
$http.get("/products/list").then(function (resp) {
products = resp.data;
deferred.resolve(products);
},function(error){
deferred.reject(error);
});
return deferred.promise;
}
}]);
And Your method in controller should handle success and error callbacks :
$scope.loadProducts = function () {
getListProducts.loadProducts().then(function(response){
$scope.products=response;
},function(error){
//your processing logic
});
}
I hope this would help you.
I am creating a service called ActiveUserProfileService, but when I call its function in a controller I get undefined as a result and I cannot figure out why. The strangest part is that, in the ActiveUserProfileService service, the information from the UserService is displayed through console.log, so I'm receiving the information, but after calling the ActiveUserProfileService in the controller, it gives me undifened. It seems like the data isn't passed around. Can someone help me ?
UserService.js:
(function () {
'use strict';
angular
.module('myApp')
.factory('UserService', UserService);
UserService.$inject = ['$http'];
/* #ngInject */
function UserService($http) {
var service = {
getAuthenticatedUser: getAuthenticatedUser,
getUserInformation: getUserInformation
};
return service;
function getUserInformation(idUser) {
return $http.post('api/user/details', {idUser: idUser});
}
function getAuthenticatedUser() {
return $http.get('api/user');
}
}
})();
ActiveUserProfileService.js
(function () {
'use strict';
angular
.module('myApp')
.factory('ActiveUserProfileService', ActiveUserProfileService);
ActiveUserProfileService.$inject = ['$http','UserService'];
/* #ngInject */
function ActiveUserProfileService($http, UserService) {
var service = {
isAccount: isAccount
};
return service;
////////////////
function isAccount(accountName) {
UserService.getAuthenticatedUser()
.then(function (response) {
var data = response.data;
UserService.getUserInformation(data.user.id)
.then(function (response) {
var userDetails = response.data;
console.log("It is");
console.log(accountName == userDetails.account_types[0].description_internal);
return accountName == userDetails.account_types[0].description_internal;
});
})
}
}
})();
My controller:
(function () {
'use strict';
angular
.module('myApp')
.controller('WizardController', WizardController);
WizardController.$inject = [
'UserService',
'ActiveUserProfileService'
];
/* #ngInject */
function WizardController(UserService,ActiveUserProfileService) {
var vm = this;
console.log("ActiveUserProfileService");
console.log(ActiveUserProfileService.isAccount("professional")); //is Returning me undefined
}
})
();
The point is, you're trying to return a value for isAccount inside another function, a callback. When you do that, you're returning a value to this function, and not isAccount itself, so isAccount will not return anything, undefined, then.
As you are calling an assynchronous method, then isAccount must be assynchronous as well,
Replace
function isAccount(accountName) {
UserService.getAuthenticatedUser()
.then(function (response) {
var data = response.data;
UserService.getUserInformation(data.user.id)
.then(function (response) {
var userDetails = response.data;
console.log("It is");
console.log(accountName == userDetails.account_types[0].description_internal);
return accountName == userDetails.account_types[0].description_internal;
});
})
}
with
function isAccount(accountName) {
var deferred = $q.defer();
UserService.getAuthenticatedUser()
.then(function (response) {
var data = response.data;
//when the user is loaded, then you resolve the promise you has already returned
UserService.getUserInformation(data.user.id)
.then(function (response) {
var userDetails = response.data;
console.log("It is");
console.log(accountName == userDetails.account_types[0].description_internal);
deferred.resolve(accountName == userDetails.account_types[0].description_internal);
return; //here is not isAccount return, but anonymous inner function 'function (response)', you got it?
});
});
return deferred.promise; //return as soon as creates the promise
}
For sure you'd have to inject $q service as well
N.B: I'm pretty much new to angularJS programming. What I'm trying to do is, to save info returned by a service to an object. My object looks like this.
var userObject = {
"id": "1",
"firstName": "Amelia",
"lastName": "Earheart"
};
I have a factory that returns data from back end and it looks like this:
.factory('myService', function($http) {
var baseUrl = 'backendservice/';
return {
myInfo:function() {
return $http.get(baseUrl + 'getmyInfo');
}
};
})
And this is how my Controller communicates with the factory service:
.controller('myController', function($routeParams,myService) {
var my = this;
my.basicInfo = function () {
//to get my info
myService.myInfo().success(function(data) {
my.activeUser.myData.id = data.id;
my.activeUser.myData.firstName = data.firstName;
my.activeUser.myData.lastName = data.lastName;
});
};
my.addSomething = function(post) {
var userObject = my.basicInfo();
};
});
and this is how I assign the data to userObject
var userObject = my.basicInfo();
I don't know why it's not working. Factory service runs but the value is not assigned to userObject.
My Controller as whole looks like this:
(function() {
angular
.module('myApp.spa', [])
.factory('myService', function($http) {
var baseUrl = 'backendservice/';
return {
myInfo:function() {
return $http.get(baseUrl + 'getmyInfo');
}
};
})
.controller('myController', function($routeParams,myService) {
var my = this;
my.basicInfo = function () {
//to get my info
myService.myInfo().success(function(data) {
my.activeUser.myData.id = data.id;
my.activeUser.myData.firstName = data.firstName;
my.activeUser.myData.lastName = data.lastName;
});
};
my.addSomething = function(post) {
var userObject = my.basicInfo();
};
});
})();
Your function my.basicInfo() does not return anything so the value of your variable userObject is undefined. Also if you want to use userObject on view expose it on your controller instance as my.userObject.
If you want to assign a value to userObject, do it either within the success callback of my.basicInfo() method or return a promise from the method my.basicInfo() and assign the value in then callback of the promise
Approach 1
my.basicInfo = function () {
//to get my info
var activeUser = {};
return myService.myInfo()
.then(function(response) {
angular.extend(activeUser, response.data);
my.userObject = activeUser;
});
};
Approach 2
my.basicInfo = function () {
//to get my info
var activeUser = {};
return myService.myInfo()
.then(function(data) {
angular.extend(activeUser, response.data);
return activeUser;
});
};
my.addSomething = function(post) {
my.basicInfo()
.then(function (response) {
my.userObject = response;
});
};
Reason is my.basicInfo does not return anything and also from $http.success/failure, you can not return any value.
So in this case, following steps you would have to do:
Define var userObject at the top of your controller so that can be accessible to all the methods.
Assign data to userObject inside success callback of $http
(function() {
angular
.module('myApp.spa', [])
.factory('myService', function($http) {
var baseUrl = 'backendservice/';
return {
myInfo:function() {
return $http.get(baseUrl + 'getmyInfo');
}
};
})
.controller('myController', function($routeParams,myService) {
var my = this;
var userObject;
my.basicInfo = function () {
//to get my info
myService.myInfo().success(function(data) {
my.activeUser.myData.id = data.id;
my.activeUser.myData.firstName = data.firstName;
my.activeUser.myData.lastName = data.lastName;
userObject = data;
});
};
my.addSomething = function(post) {
my.basicInfo();
};
});
})();
.factory('UserInfo', function($resource, apiHost) {
return $resource(apiHost + '/userinfo/:userId');
});
.controller('myController', function($routeParams,UserInfo) {
var vm = this;
// suppose that you have stored the userId somewhere after the login
vm.userObject = {};
var myUserInfo = UserInfo.get({
userId: userId
});
vm.refreshData = function (){
myUserInfo.$promise
.then(function(response) {
vm.userObject = response;
}, function(error) {
// doSomething
});
};
vm.update = function(){
myUserInfo.save(vm.userObject, function() {
// console.log('success');
}, function(error) {
// console.log('error');
});
};
});
this is my object that get from a service.
this is my controller.
var user = useroneService.getLoggedUser(user);
console.log(user);
console.log(user.data);
I got a undefined when I try to access the data. How do I access to the Object data?
user.service.js
'use strict';
angular.module('app').service('userService',['authService', 'userTransformer','LoggedUser', function(authService, userTransformer, LoggedUser) {
this.getLoggedUser = function(user){
return authService.login(user).then(function (response) {
var loggedUser = userTransformer.transform(response.data);
});
};
}]);
logged.user.js
angular.module('app').value('LoggedUser', function () {
var LoggedUser = function () {
this.dispalyName = '';
this.token = '';
this.logged = false;
};
LoggedUser.prototype = {
};
});
user.transformer.js
angular.module('app').factory('userTransformer',['LoggedUser', function (LoggedUser) {
//logged user transform
var transformObject = function (response) {
var model = new LoggedUser();
angular.extend(model, response);
return model;
};
return {
transform: transformObject
};
}]);
flow
AuthService(get data)==>UserService(data transform to LoggedUser using the transformer)
==>LoginController
You are not returning a promise. Change your controller code to:
useroneService.getLoggedUser(user).then(function(data) {
var user = data;
console.log(user);
})
One more thing, you are not returning the response from your service:
return authService.login(user).then(function (response) {
var loggedUser = userTransformer.transform(response.data);
return loggedUser; //add this
});
I have the following factory:
app.factory('clientFactory', function ($http) {
var factory = {};
factory.getClients = function () {
var url = "/tracker/api/client";
$http.get(url).then(function (response) {
return response.data;
});
};
factory.getClient = function (id) {
// TODO
};
factory.insertClient = function (firstName, lastName, city) {
// TODO
};
factory.deleteClient = function (id) {
// TODO
};
return factory;
});
And the controller:
app.controller('ClientController', function ($scope, clientFactory) {
$scope.clients = [];
init();
function init() {
$scope.clients = clientFactory.getClients();
}
$scope.insertCustomer = function () {
// TODO
};
$scope.deleteCustomer = function (id) {
// TODO
};
});
In my controller, 'clients' is always null. I've tried a couple of other approaches like what I see here but I got an error that 'success cannot be called on null' and if I make it past that error, my success function is never called.
What am I missing here?
In your controller, you are treating the getClients method as if it were synchronous. Remember that when you do $http.get, a promise is returned. You need to return that promise to the controller, so it can call .then with a method which will handle a successful result.
Your getClients method needs to look like this:
factory.getClients = function () {
var url = "/tracker/api/client";
return $http.get(url);
};
And I believe your init method needs to look like this:
function init() {
clientFactory.getClients().then(function(response) {
$scope.clients = response.data;
});
}
Try that out!