Recently I started learning AngularJS. My problem is as follows.
I cannot access the data returned by $http.get() out side the method call.
Code :
(function(){
var productApp = angular.module('productApp', []);
productApp.controller('ProductController', ['$http', function($http){
var store = this;
store.products = [];
$http.get('http://localhost:8080/VeggieFresh/veggie/product/1')
.success(function(data){
store.products = data;
console.log(data);
});
console.log(store.products);
}]);
})();
When I print data inside $http.get() method, it could be printed without any problem, but when i try to print it outside method; it displays empty array.
I guess because of this I cannot access this data on HTML as well.
Any help in this regards is highly appreciated.
Since $http success is a asynchronous call you wont get data immediately outside the function you can call a function for "success" function , or use a callback function
As far as your code is concerned, you can save data on $scope variable
$http.get('http://localhost:8080/VeggieFresh/veggie/product/1')
.success(function(data){
$scope.store.products = data;
//console.log(data);
});
The success function runs async, so you will get the result inside success function.
Following code worked for me.
productApp.controller('ProductController', ['$http', function($http){
var store = this;
store.products = [];
var promise = $http.get('http://localhost:8080/VeggieFresh/veggie/product/1');
promise.success(function(data){
store.products = data;
});
}]);
Related
I have this problem that is taking up too much of my development time. I have researched this problem a lot and it has now gotten me to here.
I'm making a GET request from a service. The GET request is being called from a controller.
Here is the service that makes the GET request, ajaxSrvc.js:
app.service('ajaxSrvc', ['$log', 'Constants', '$http', '$q',
function($log, Constants, $http, $q) {
this.getAllTasks = function() {
var defer = $q.defer();
var url = 'http://localhost:9998/tasks';
$http.get(url, {cache: 'true'})
.success(function(data) {
defer.resolve(data);
});
return defer.promise;
};
}
]);
That request is invoked from this controller, tasksCtrl.js:
app.controller('tasksCtrl', ["$log", "$scope", "Constants","$location", "ajaxSrvc",
function($log, $scope, Constants, $location, ajaxSrvc) {
var someData = null;
ajaxSrvc.getAllTasks().then(function(data) {
console.log(data);
someData = data;
});
console.log(someData); // This is printing NULL
}
]);
The problem arises when I try to print out someData, it prints as NULL instead of containing information from the GET request.
How do I get around this?
The problem is that you need to wait to the async function to finish. When you do console.log(someData) The code is still loading the data inside the async function. You can add a function call inside the .then function, that will execute after the load finish.
If console.log(data) is returning the expected value you should do something like this:
app.controller('tasksCtrl', ["$log", "$scope", "Constants","$location", "ajaxSrvc",
function($log, $scope, Constants, $location, ajaxSrvc) {
var someData = null;
ajaxSrvc.getAllTasks().then(function(data) {
console.log(data);
someData = data;
callWhenFinish();
});
function callWhenFinish(){
console.log(someData);
}
}
]);
This doesn't work because this is a asynchronous action, so basically the console.log(someData) is getting called before you actually get the data. It will never work.
Since getAllTasks() is a promise , someData will log first before the promise is ready.. So instead of assigning your callback data to someData within the callback scope , just pass data to a function instead then do whatever from there..
Example :
ajaxSrvc.getAllTasks().then(function(data) {
doSomethingWithData(data);
});
//Then
$scope.doSomethingWithData = function(data){
$scope.someData = data;
console.log($scope.someData);
}
Hope this helps.
I have a json file. I want to get the data from that file using $http.get and store that in variable so that I can use it later in the controller. Something like this:
$http.get('items.json').success(function(response){
var data = response; //data can't be used outside this function
})
I want to use data outside the function.
You can do it in the below fashion:
var data;
$http.get('items.json').success(function(response){
data = response; //data can't be used outside this function
})
here data now will be accissible to all the methods of your controller.
But my suggestion is to make one angular service and put $http code inside it. And then inject this service
inside your controller and use it.
Below would be the code:
Service Code:
app.service('MyService', function($http) {
this.getData = function(successHandler, failureHandler) {
$http.get('items.json').then(function(response){
successHandler(response); //data can't be used outside this function
}, function(response) {
failureHandler(response);
})
}
});
Controller Code:
app.controller('MyCntrl', function($scope, MyService) {
var data;
function successHandler(res) {
data = res;
}
function failureHandler(res) {
data = res;
}
$scope.getData = function() {
MyService.getData(successHandler, failureHandler);
}
});
The above solution would help you to separate out the concerns related to service and controller and to make your application
more modular and maintainable.
You can create data outside that function. like
var data;
$http.get('items.json').success(function(response){
data = response; //data can't be used outside this function
});
But in this way also data will be undefined unless get call gives response, evenif you are using JSONP from local.
Ideal way to do this is using promises. as below
var callService = function(){
return $http.get('items.json').success(function(response){
return response; // Response variable will be input to promise
});
};
callService.then(function(data){
// this data variable will be equal to response.
});
Further reading on
https://docs.angularjs.org/api/ng/service/$q
dont create a variable inside call, declare that variable outside and just assign value for it.
var data;
$http.get('items.json').success(function(response){
data = response; //data can't be used outside this function
});
as all mentionned create the variable outside the function.
BUT USE THEN instead of success because it is depreceted
Deprecation Notice
The $http legacy promise methods success and error have been deprecated. Use the standard then method instead. If $httpProvider.useLegacyPromiseExtensions is set to false then these methods will throw $http/legacy error.
var data;
$http({
method: 'GET',
url: '/someUrl'
}).then(function successCallback(response) {
// this callback will be called asynchronously
// when the response is available
console.log(reponse); // response contain status , data, headers, config...
data = response.data ;
}, function errorCallback(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
Hi I have created a service which gets a json from a remote server, not I need to get the result and set it as a property of the service, but I don't know how to get the property out of the function
app.service('varService',['$http', function($http){
var ip = myip;
window.city = '';
$http.get('http://ip-api.com/json/'+ip)
.then(function(data) { window.city = data.data.city; });
this.city=city;
}]);
the property this.city doesn't receive any value , however when I do console.log inside .then() the value exists, how do I solve the problem, how do I get value out of $http.then()?
Because $http.get returns a promise, when you assign the city value, the request hasn't actually returned from the web server yet.
You need to return the promise from your service and instead handle your .then() callback handler in your invoking controller.
app.service('varService',['$http', function($http){
var ip = myip;
this.getIp = $http.get('http://ip-api.com/json/'+ip);
}]);
// controller
varService.getIp.then(function(data) { window.city = data.data; });
This is the recommended approach by the John Papa AngularJS Styleguide and it allows you to chain multiple promises together.
There you can't get data return by ajax as soon as you execute that line of code, you should use .then callback to retrieve data over there. You could use .then over $http call to get data from ajax.
app.service('varService',['$http', function($http){
var ip = myip;
var self = this;
self.getCity = function (){
return $http.get('http://ip-api.com/json/'+ip)
.then(function(data) {
self.city = data.data.city;
return self.city; //do return city retrieved
});
}
}]);
I have a simple Angular service that uses $http to make a call to an API.
app.service("MyService", function($http){
this.api = function(obj){
return $http.post("/some-route", obj).success(function(data){
//process data in various ways here
var returnObj = {
complete: true,
data: data
};
return returnObj;
});
}
});
In the $http callback, I process the data before returning it. When I call this service in my controller, I want to get that processed data.
The following only gives me the unprocessed data:
MyService.api(someObj).success(function(data){
console.log(data);
});
How do I get the processed data from the callback?
The success function does not create a new promise, so your controller success callback is registered to the same promise as the service (the original one).
Instead you can use then, so it will create a new promise which will be resolved with your returnObj object:
// service
return $http.post("/some-route", obj).then(function(data){
// controller
myService.api().then(function(data) {
I have tested up your code in a plunker, and guess what? Its working for me. Can you please confirm it, or send me more info, i'm glad if i could help.
Plunker
var app = angular.module('plunker', []);
app.service("MyService", function($http){
this.api = function(obj){
return $http.post("http://jsonplaceholder.typicode.com/posts", obj).success(function(data){
//process data in various ways here
console.log(data);
var returnObj = {
complete: true,
data: data
};
return returnObj;
});
}
});
app.controller('MainCtrl', function($scope,MyService) {
$scope.data = 'World';
MyService.api({oi: true}).success(function(data){
$scope.data = data
});
});
Update:
I have misunderstood your question. You want to process the data in the callback to manipulate it in your action. Your code dont work because success() actually returns a promise, but it dont change it, it returns the original one. The one to go for is the then(), which is chainable and returns the modified version of the promise.
I've made changes to the plunker to reflect my new vision of the scenario. Here is the new code.
Thanks for your time.
var app = angular.module('plunker', []);
app.service("MyService", function($http){
this.api = function(obj){
return $http.post("http://jsonplaceholder.typicode.com/posts", obj).then(function(data){
//process data in various ways here
console.log(data);
var returnObj = {
complete: true,
data: data
};
return returnObj;
});
}
});
app.controller('MainCtrl', function($scope,MyService) {
$scope.data = 'World';
MyService.api({oi: true}).then(function(data){
$scope.data = data
});
});
New Plunker
Please forgive me if this is a simply problem for an angular guru, i am fairly new to services.
Below is a snippet of my controller where i have attempted make a service request to call out data from my JSON file "jobs.json".
I am not receiving an data when i load my web page neither i am seeing the JSON file in inspector element.
I assume there's something incorrect in my below code. Does anyone what the issue is?
Click here if you need to play about with the code
"use strict";
var app = angular.module("tickrApp", []);
app.service("tickrService", function ($http, $q){
var deferred = $q.defer();
$http.get('app/data/items.json').then(function (data){
deferred.resolve(data);
});
this.getItems = function () {
return deferred.promise;
}
})
.controller('tickCtrl', function($scope, tickrService) {
var promise = tickrService.getItems();
promise.then(function (data){
$scope.items= getData;
console.log($scope.items);
});
In your Plunkr, you had a few errors, such as the <script> tags around the wrong way (you need to have Angular first, so your code can then use angular.module). You also had the wrong attribute of ng-app-data instead of data-ng-app.
The key problem was with the JS code, the first parameter to the success handler for the $http.get() call is an object with a data property, which is the actual data returned. So you should resolve your promise with that property instead.
Then in the controller, like Michael P. said, getData is undefined, you should use the data parameter passed in.
app.service("tickrService", function($http, $q) {
var deferred = $q.defer();
$http.get('jobs.json').then(function(response) {
deferred.resolve(response.data);
});
this.getjobs = function() {
return deferred.promise;
}
})
.controller('tickCtrl', function($scope, tickrService) {
var promise = tickrService.getjobs();
promise.then(function(data) {
$scope.jobs = data;
console.log($scope.jobs);
});
});
See forked Plunkr.
In the success handler of your getItems function, you are storing getData, which is undefined. You want to store data instead.
Therefore, in the controller, your call to getItems() should be as follows
tickrService.getItems().then(function (data) {
$scope.items = data;
});
Also, you want to make the $http call in getItems. Like that :
this.getItems = function () {
var deferred = $q.defer();
$http.get('app/data/items.json').then(function (data) {
deferred.resolve(data);
});
return deferred.promise;
}
However, you can avoid the above boilerplate code around the promises, because $http.get returns itself a promise. Your service and controller could be much more concise and less polluted by boilerplate code.
The service could be as simple as :
app.service("tickrService", function ($http) {
this.getItems = function () {
return $http.get('app/data/items.json');
}
});
And the controller could be shortened to:
app.controller('tickCtrl', function ($scope, tickrService) {
tickrService.getItems().then(function (response) {
$scope.items = response.data;
})
});
Please note that the response resolved by $http is an object that contains (link to doc) :
data – The response body transformed with the transform functions.
status – HTTP status code of the response.
headers – {function([headerName])} – Header getter function.
config – The configuration object that was used to generate the request.
statusText – HTTP status text of the response.
Therefore in the success handler of getItems we are storing response.data, which is the response body, and not the whole response object.