I am trying to use $resource to get data from a static json file and here is the code snippet :
angular.module('app.services', ['ngResource']).
factory('profilelist',function($resource){
return $resource('services/profiles/profilelist.json',{},{
query:{method:'GET'}
});
});
In the controller,
function ProfileCtrl($scope,profilelist) {
$scope.items = [];
$scope.profileslist = profilelist.query();
for (var i=0;i<=$scope.profileslist.length;i++){
if($scope.profileslist[i] && $scope.profileslist[i].profileid){
var temp_profile = $scope.profileslist[i].profileid;
}
$scope.items.push(temp_profile);
}
But now, I am facing an error :
TypeError: Object #<Resource> has no method 'push'
Could you please help me where I am going wrong ?
You don't need to specify actions parameter for default $resource methods (these are 'get', 'save', 'query', 'remove', 'delete'). In this case you can use .query() method as is (this requires only service definition to be chaged):
angular.module('app.services', ['ngResource']).
factory('profilelist',function($resource){
return $resource('services/profiles/profilelist.json');
});
P.S. And one more hint is that your example unwrapped json into hash rather then array (that's why you received no push method error), if you need it to be an array set isArray: true to action config:
'query': {method:'GET', isArray:true}
And as #finishingmove spotted you really can't assign $resource result to obtain immediately, provide callback:
$scope.profileslist = profilelist.query(function (response) {
angular.forEach(response, function (item) {
if (item.profileid) {
$scope.items.push(item.profileid);
}
});
});
Related
I have a problem with angular-ui typeahead component. It does not show values populated by angular resources, however using $http works well. I suppose I missing some trick here with asycn call and correct population of returned values.
Working code
$scope.searchForContact = function(val) {
return $http.get('/api/contacts/search', {
params: {
q: val
}
}).then(function(response){
return response.data.map(function(item){
return item.name;
});
});
};
Not working code
$scope.searchForContact = function(val) {
return Contact.search({q: val}, function(response){
return response.map(function(item){
return item.name;
});
});
});
...
'use strict';
app.factory("Contact", function($resource, $http) {
var resource = $resource("/api/contacts/:id", { id: "#_id" },
{
'create': { method: 'POST' },
'index': { method: 'GET', isArray: true },
'search': { method: 'GET', isArray: true, url: '/api/contacts/search', params: true },
'show': { method: 'GET', isArray: false },
'update': { method: 'PUT' },
'destroy': { method: 'DELETE' }
}
);
return resource;
});
Pug template code
input.form-control(
type='text'
ng-model='asyncSelected'
uib-typeahead='contact for contact in searchForContact($viewValue)'
typeahead-loading='loadingLocations'
typeahead-no-results='noResults'
)
i.glyphicon.glyphicon-refresh(ng-show='loadingLocations')
div(ng-show='noResults')
i.glyphicon.glyphicon-remove
|
|No Results Found
Angular resources are working fine, including search endpoint - I just output on page result returned by the search endpoint. In both results should be just an array with string values. What am I doing wrong?
The difference between $http.get and your Contact.search is that the first one returns a promise and the latter doesn't. Any $resource method will usually be resolved to the actual response. I'll show that with an example.
Getting data with $http
var httpResult = $http.get('http://some.url/someResource').then(function(response) {
return response.map(function(item) { return item.name });
});
The httpResult object contains a promise, so we need to use then method to get the actual data. Moreover, the promise will be resolved to the mapped array, which is the expected result.
Getting data with $resource
var someResource = $resource('http://some.url/someResource');
var resourceResult = someResource.query(function(response) {
return response.map(function(item) { return item.name });
});
The resourceResult isn't a promise here. It's a $resource object which will contain the actual data after the response comes from the server (in short, resourceResult will be the array of contacts - the original, not mapped, even though there is a map function). However, the $resource object contains a $promise property which is a promise similar to one returned by $http.get. It might be useful in this case.
Solution
I read in documentation that in order to make uib-typehead work properly, the $scope.searchForContact needs to return a promise. Instead of passing the callback function to search, I would simply chain it with the $promise from $resource object to make it work.
$scope.searchForContact = function(val) {
return Contact.search({q: val}).$promise.then(function(response){
return response.map(function(item){
return item.name;
});
});
});
Let me know if it works for you.
I have an angularjs data factory that makes a server call and sets the returned data in the factory returned object like this
angular.module('app').factory('DataService', function() {
// Returning object
return {
data: {},
isLoaded: false,
getData:getdata
};
function getData() {
var self = this;
//Some Ajax Call returns an 'dataObject'
self.data = dataObject; //dataObject has a few subObjects and list
}
});
Now inside my angularjs controller I am making call to the DataService.getData() to make ajax call and hence set the returned dataObject within factoryobject 'data'
and I have declared it in controller like this
appV.data = DataService.data;
If I try to print it on console or access like this
console.log(appVm.data), I am able to access it, but if I try to access any subObjects like Ex - appVm.data.property1 or appVm.data.subObject1.subObject1.property, it gives undefined.
Can someone please explain why this behavior is occuring ?
Thanks in Advance
It is just example:
app.factory("messageService", function($q){
return {
getMessage: function(){
return $q.when("Hello World!");
}
};
});
And now the routing configuration that will use the service in a resolve.
$routeProvider
.when("/news", {
templateUrl: "newsView.html",
controller: "newsController",
resolve: {
message: function(messageService){
return messageService.getMessage();
}
}
})
These link may help you:
Link 1,
Link 2
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 using ngResource to get the data from the server side into my view, and I have a custom action that I defined that gets items count, it looks like this in the code (controller):
$scope.totalItems = Item.item_count().total
And in my view :
This customer bought {{totalItems}}
In my view I just get the This customer bought without other part being interpolated. However also when I do this :
console.log(Item.item_count().total)
console.log(Item.item_count())
I get the undefined for first statement but for second one I get this :
Why am I unable to access the total count from the view, and what do I do to fix this?
Update (service code) :
app.factory('Item', function($resource) {
return $resource(
window.config.API_URL + '/:apiPath/:id', {
id: '#id',
apiPath: '#apiPath'
}, {
query: {
method: 'GET',
params: {
apiPath: 'items'
},
isArray: true
},
item_count: {
method: 'GET',
params: {
apiPath: 'item_count'
},
isArray: false
}
}
);
});
You need to get the $promise and pass in a callback like so:
Item.item_count().$promise.then(function(data) {
$scope.totalItems = data.total;
});
If you need to have the data resolved before loading your view, you can use $stateProvider to resolve it. This should give you a good idea how and some implications of using it: http://www.codelord.net/2015/06/02/angularjs-pitfalls-using-ui-routers-resolve/.
look like you get a promise returned.
Try calling console.log(Item.item_count().then(function(data) {
console.log(data);
});
Without seeing your other code my guess is the line
$scope.totalItems = Item.item_count().total is getting resolved before the promise is getting resolved. That line should be in sort of then catch for the promise. However this is just a guess since you haven't actually posted this code.
Because Item.item_count() returns a promise you have to wait until it is resolved before you set $scope.totalItems:
Item.item_count().then(function(item_count) {
$scope.totalItems = item_count.total;
});
Try removing the scope. from your {{}} in the view.
This customer bought {{totalItems}}
I am attempting to build a generic filter which needs to be able to handle - based on configuration - parameters. Both a resource instance and a service.
I have the following factory code:
angular.module('sample').factory('Sample', function($resource) {
var methods = {
search: {
method: 'POST',
isArray: true
}
}
var Sample = new $resource('/sample', methods);
Sample.prototype.elasticFilter = function (search) {
var query = {
query: {
filtered: {
query: {
wildcard: {
name: '*' + search.toLowerCase() + '*'
}
}
}
}
}
return this.$search(query);
}
return Sample;
});
Now if I do the following in my directive:
scope.search = function (search) {
Sample.elasticFilter(search).$promise.then(function () {
handle
});
this results in
TypeError: Cannot read property 'then' of undefined
printing out Sample.elasticFilter(search), the result is directly a Promise.
Modifying the directive to read directily off Sample.elasticFilter(search).then results in:
TypeError: value.push is not a function.
For non-instance-resources (e.g. NOT newed up, rather service directly), .$promise works fine.
Why is this happening? How can I work around it? When does a resource have a $promise, and when does it not?
This appears to be a "feature" https://github.com/angular/angular.js/issues/11767
The only way to really work around this is to not use isArray on instance level resource methods.