I'm trying to call a list of articles from the NPR API. I have a working URL which returns as JSON. However, somewhere in my controller, I'm getting lost getting the object. When I console.log it to test, it returns as [object Object] and nothing else. My service looks like this:
app.factory('nprService', function($resource) {
//call npr api
return $resource('http://api.npr.org/queryid=61&fields=title,byline,text,image,all&output=JSON...
and my controller:
app.controller('ArticleListCtrl', function($scope, nprService) {
//call the service and store as a variable
$scope.article = nprService.get();
});
I've tried using query to get the result, like this, but it's returning a single JSON object so that obviously didn't work.
//call the service and store as a variable
nprService.query(function(data) {
$scope.article = data;
});
Any help would be greatly appreciated. Thanks in advance.
You need to use a promise construct to get at the data. The controller code can be re-written as:
app.controller('ArticleListCtrl', function($scope, nprService) {
//call the service and store as a variable
nprService.get().then(function(result){
$scope.article = result.data;
});
The $resource.get() function returns a promise. It should be used this way:
nprService.get().success(function(data, status, headers, config){
$scope.article = data;
}).error(function(data, status, headers, config){
console.log(status);
});
Using Angular 6 you can try this
myFunctionName(){
this.http.get(`http://www.thesoftdesign.com`)
.map(res => res.json())
.subscribe(data => {
this.data = data;
console.log('data', this.data);
});
}
Related
I am trying to get data back from a web service, I have to approaches the first is calling the data from the controller which works here is the code
$http({
method: 'POST',
url: 'https://url_json.php',
headers: {'Content-Type': 'application/x-www-form-urlencoded; charset-UTF-8'},
transformRequest: function(obj) {
var str = [];
for(var p in obj)
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
return str.join("&");
},
data: paramsVal
}).then(function(response){
$scope.myData = response.data.PlaceDetailsResponse.results[0].first_name;
console.log('my data',$scope.myData);
});
}
but I would like to share the data between controllers so I read service is the best options, so in my services.js I have:
.factory('userService', function($http){
return {
getUsers: function(){
return $http.post("https://url_json.php",
{entry : 'carlo' ,
type:'first_name',
mySecretCode : 'e8a53543fab6f00ebec85c535e'
}).then(function(response){
users = response;
return users;
});
}
}
})
but when I call it from the controller with var user = userService.getUsers(); returns the below in the console:
user is [object Object]
and inspecting element within chrome I only see:
user is Promise {$$state: Object}
Also in chrome when I drill down on Promise the data value = "".
Can anyone take a look at my services and see if I'm doing anything wrong.
Thanks
.then returns a promise. You're falling for the explicit promise construction antipattern.
getUsers: function(){
return $http.post("https://url_json.php",
{entry : 'carlo' ,
type:'first_name',
mySecretCode : 'e8a53543fab6f00ebec85c535e'
})
}
The above is all you need. Then, in your controller:
userService.getUsers()
.then(function(response) {
$scope.data = response.data; // or whatever
});
I would recommend looking at John Papa AngularJS style guide. He has a lot of information about fetching service data, using it in controllers, etc.
In your controller you will have to assign the user variable by resolving the promise return from the getUsers like below:
$scope.user = [];
$scope.error ="";
userService.getUsers().then(function(data){
$scope.user = data
},function(err){
$scope.error = err;
});
Hope this helps.
I'm trying to pass a params object to the $http.get() service. My params look like this:
var params = {
one: value,
two: value
}
And I'm trying to pass them into my function like so:
$http.get('/someUrl', params)
.success(function(data) {
// stuff
})
.error(function(data) {
// error stuff
});
Is this the correct way to go about doing this?
The second argument of $http is a config object (see documentation). Amongst other properties, the config object accepts a params property:
params – {Object.<string|Object>} – Map of strings or objects which will be serialized with the paramSerializer and appended as GET parameters.
Therefore you have to pass the parameters as such
var config = {
params: {
one: value,
two: value
}
}
$http.get('/someUrl', config).then(...)
Suppose the values for the parameters are respectively '1' and '2', $http will send a GET request to the following url:
/someUrl?one=1&two=2
As a side note, try to avoid using success and error functions on $http. They have been deprecated as of angular 1.4.4. Use the methods then with a success and an error callback instead, or then with only a success callback and catch.
Service/Factory
For the actual call use a factory or service that you can inject to the controllers you need it in. This is an example factory passing parameters
.factory('Chats', function ($http, $rootScope, $stateParams) {
return {
all: function () {
return $http.get('http://ip_address_or_url:3000/chats', { params: { user_id: $rootScope.session } })
}
};
});
Controller
In your controller you use the service like this
.controller('ChatsCtrl', function ($scope, Chats) {
Chats.all().success(function (response) {
$scope.chats = response;
})
})
I have faced similar issue in recent time and I had to add few additional details to request (I used accepted answer with some headers):
$http.get(url, {
params: {
paramOne: valueOne,
paramTwo: valueTwo,
...
},
headers: {
'key': 'value'
},
// responseType was required in my case as I was basically
// retrieving PDf document using this REST endpoint
// This is not required in your case,
// keeping it for somebody else's reference
responseType: 'arraybuffer'
}).success(
function(data, status, headers, config) {
// do some stuff here with data
}).error(function(data) {
// do some stuff here with data
});
The $http documentation suggest that the second argument to the $http.get method is an object which you can pass with it "param" object.
Try something like this:
$http.get('/someUrl', {params: params})
.success(function(data) {
// stuff
})
.error(function(data) {
// error stuff
});
I'm currently trying to access the access the Google Books API, which I have successfully managed to do directly in my controller, but for the sake of best practices I am wanting to move the business logic into a directive.
HTML
<form ng-submit="search(data)">
<div class="list">
<div class="list list-inset">
<label class="item item-input">
<input type="text" placeholder="Search by Book Title" ng-model="data.isbn">
</label>
</div>
<button class="button button-block button-positive" type="submit">
Find Book
</button>
</div>
Above I'm attaching data.isbn to the search() function.
Controller.js
.controller('DashCtrl', function($scope, BookSearch) {
$scope.search = function(data) {
$scope.books = BookSearch(data).all();
};
})
I am then feeding that parameter to my BookSearch service.
Service.js
.factory('BookSearch', function ($http) {
return function(data) {
var api = "https://www.googleapis.com/books/v1/volumes?q=" + data;
// Simple GET request example :
$http.get(api).
success(function(data, status, headers, config) {
var books = data;
}).
error(function(data, status, headers, config) {
console.log(status);
});
}
return {
all: function() {
return books;
}
}
});
In the services.js I am wanting to access the Books API from Google with the search parameter and then write several functions, one of them being all() to simply return the books to $scope.books in the controller.
I'm receiving this error:
TypeError: Cannot read property 'all' of undefined
When I try to make an http call inside the all() function, then $http.get does not even execute, as I am unable to log neither success nor error case and $scope.books remains undefined.
I am trying to stick with best practices in building a neat and scalable app and learning angular the way it should be.
I've looked at so many tutorials but they only ever use $http.get calls to static JSON files without parameters from the user.
Could anyone please advise whether I am going about this the right way and where my error is?
Think you're having trouble understanding how promises work in angular. Promises are asynchronous so you can't just do $scope.books = BookSearch(data).all();. You need to wait for the response from BookSearch(data).all() and then set the $scope.books in a success callback function. Hopefully this article will help you
Change your service to
.factory('BookSearch', function ($http) {
return {
all: function(data) {
var api = "https://www.googleapis.com/books/v1/volumes?q=" + data;
// Simple GET request example :
return $http.get(api).
success(function(data, status, headers, config) {
// This is the callback function when the $http.get completes successfully so you can remove it
return data;
}).
error(function(data, status, headers, config) {
console.log(status);
});
}
}
});
and your controller to:
.controller('DashCtrl', function($scope, BookSearch) {
$scope.search = function(data) {
BookSearch(data).all().then(function(data) {
// This is the callback function when BookSearch(data).all completes successfully
$scope.books = data;
}
};
})
New to angular here. I am trying to data then pass it into a factory for use. I am trying to get the events to fire in a certain order with using the $http within angular. I was pointed in the direction of using .run to do the first population, pass it into the factory, which then passes it into the controllers. The factory has a function which then would allow me to "refresh" the data being shared with the controllers.
I received some great help setting up the refresh function, but I am struggling get the data to populate initially. Here is my attempt:
.run("getDataForLevels", function($http){
var getIt = $http.get("/assets/images/generated.json")
.success(function(data){
return data;
});
return getIt;
})
.factory("UserService", function($http, getDataForLevels) {
dataFactory = getDataForLevels;
dataFactory.currentData = null;
dataFactory.update = function () {
return $http.get("/assets/images/generated.json")
.success(function(data){
dataFactory.currentData = data;
return data;
});
};
return dataFactory;
});
I then Add the dependency of UserService to the controllers and pass in the data to the controllers. I seem to be betting an error [ng:areq] on this. Any/all help would be much appreciated. Thanks!!
you can't do like this :
.run("getDataForLevels", function($http){
var getIt = $http.get("/assets/images/generated.json")
.success(function(data){
return data;
});
return getIt;
})
it only take one argument, as a function.
you can do like this:
.run(function($http,$rootScope){
$http.get("/assets/images/generated.json")
.success(function(data){
$rotScope.data=data;
});
})
.factory("UserService", function($http, $rootScope) {
dataFactory.update = function () {
return $http.get("/assets/images/generated.json")
};
return dataFactory;
});
in controller inject dependencies and do like this:
var dataFactory = $rootScope.data;
dataFactory.currentData = null;
UserService.update ()
.success(function(data, status, headers) {
console.log(data);
})
.error(function(data, status, headers, config) {
console.error('error in loading File list');
});
i am having a problem accessing the $scope. as it seems it is not working for me.
i have a resource:
squashApp.factory('CourtsService', function($resource) {
return $resource('/api/court/:num', {num: '#num'});
});
and my controller does:
squashApp.controller('CourtsController',
function CourtsController($scope, $window, $http, CourtsService) {
CourtsService.get({num:1}, function(data){
$scope.courts = data;
})
});
my server succeeds in returing a data which is in format of javascript object (JSON).
i have checked it. but for some reason the $scope is not updated and after this callback my view is not changing at all.
help please
I created a demo for you and your code looks ok.
However, it is always good to add some logic for the callback when the error occurs like this, so your app will not die silently.
squashApp.controller('CourtsController', function CourtsController($scope, $window, $http, CourtsService) {
CourtsService.get({
num: 1
}, function (data) {
console.log('success');
$scope.courts = data;
}, function (data) { // -> error handling
console.log('failed');
$scope.courts = data;
})
});
Demo
A simple way to access your $scope using angular $resource by using $promise (recommended)
squashApp.controller('CourtsController',
function CourtsController($scope,CourtsService) {
CourtsService.get({num:1}).$promise.then(function(data){
//$scope -- can be accessed here
}, function(failed){
}
});