My code: http://plnkr.co/edit/2blxwwyv0gS9GYui7IVn?p=preview
I defined a service:
angular.module('jsonService', ['ngResource']).factory('JsonService', function($resource) {
var jsonService = $resource('data.json/:id',
{id: "#id"}, //parameters default
{
getAll: { method: "GET", params: {} },
addNew: { method: "POST", params: { id: ":id"}},
});
return jsonService;
});
I keep getting error when I try to call getAll from my controller.
I also tried to add a new object but AddNew simply would not work from the controller.
Add isArray: true
getAll: { method: "GET", params: {}, isArray: true },
Please take a look at actions parameter from $resources.
isArray – {boolean=} – If true then the returned object for this
action is an array, see returns section.
And this is how to post data
non-GET "class" actions: Resource.action([parameters], postData,
[success], [error])
For example:
var obj = { "id": "2", "created": "3424324", "updated": "2342666", "name": "Bob" };
JsonService.addNew({ "id": "2"}, obj)
Related
I have an angularJS $resource:
$resource("http://localhost:3000/:id",{
id: '#id'
},
{
get: {
method:'GET',
isArray: false
},
foo: {
method:'POST',
url: 'http://localhost:3000/:id/foo',
isArray: false
}
});
Now if I call:
User.foo({id:'123', anotherParam: 'bar'});
This results in the URL 'http://localhost:3000/foo' being called and passing the id and anotherParam parameters as POST fields.
I actually want it to call 'http://localhost:3000/123/foo' and only pass the anotherParam parameter as a POST field.
How do I get the id parameter to behave correctly?
https://docs.angularjs.org/api/ngResource/service/$resource
non-GET "class" actions: Resource.action([parameters], postData, [success], [error])
You need to do:
User.foo({id:'123', anotherParam: 'bar'}, <post data object>);
When you call the function with a single argument. It assumes that the optional argument is not there and sends it as the postData.
The accepted solution didn't work for me (AngularJS v1.4.8).
Have to manually set content type and transform to form data.
Sample:
var DirectoryApi = $resource('api/directories', null, {
move: {
url: 'api/directories/:name/_move',
params: {"name" : "#name"},
headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'},
transformRequest: function (param) {
return $.param(param);
},
method: 'POST'
},
});
And usage:
function moveDirectory(name, parent, after) {
return DirectoryApi.move({name: name}, {parent: parent, after: after});
}
I'm working with an API that follows the JSON API spec.
http://jsonapi.org/
I'm building an app in Ionic using ngResource, and the resource.query() method expects the response to be an array:
[
{
"id": 1,
"foo": "bar"
},
{
...
}
]
But the JSON API spec passes that nested under the data attribute:
{
"data": [
{
"id": 1,
"foo": "bar"
},
{
...
}
]
}
How can I automatically post-process the response from the API to fulfill what ngResource is expecting?
Look into transformResponse and interceptor objects.
https://docs.angularjs.org/api/ngResource/service/$resource
EDIT: Adding code
$provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {
return {
'response': function(response) {
response.data = response.data.data;
return response;
}
};
});
$httpProvider.interceptors.push('myHttpInterceptor');
EDIT:
As you can see below, the query method is built to handle arrays by default.
{ 'get': {method:'GET'},
'save': {method:'POST'},
'query': {method:'GET', isArray:true},
'remove': {method:'DELETE'},
'delete': {method:'DELETE'}
};
you can use simple GET method to get object list response from your api.
OR you can change query default behavior to this way.
:
var config = { method:'GET', isArray: false };
var url = 'http://jsonapi.org';
$resource(url, {}, {query: config});
for more detail. Please check https://docs.angularjs.org/api/ngResource/service/$resource
In my resources i have following code
app.factory('myResource', function ($resource, $http) {
var resource = $resource('http://localhost:1234/api/:pg/:obj', {
pg: '#pg',
obj: '#obj'
},
{
'put': {
method: 'PUT'
},
'get': { method: 'GET' },
'save': { method: 'POST' },
'query': { method: 'GET', isArray: true },
'remove': { method: 'DELETE' },
'delete': { method: 'DELETE' }
}
);
return resource;
});
and in controller i use like
var param = { pg: 'MyTask', obj: taskModel }
$scope.TaskId = myResource.put(param);
and on debugging data is fine in obj but getting null in model
public HttpResponseMessage put(MyTask model)
{}
Your resource is configured to serialize #pg and #obj into URI.
$resource('http://localhost:1234/api/:pg/:obj', {
But WEBAPI sees MyTask object(complex object) and expects it to be from request body.
Either change client side to include "obj" data into request body or change server-side to get model from uri using webapi attributes. It all depends on complexity of "obj" information.
I define a factory for "Dashboard":
myApp.factory('Dashboard', ['$resource', function($resource) {
return $resource("/dashboards/:id", { id: "#id" },
{
'create': { method: 'POST' },
'index': { method: 'GET', isArray: true },
'show': { method: 'GET', isArray: false },
'update': { method: 'PUT' },
'destroy': { method: 'DELETE' }
}
);
}]);
In order to update a dashboard I need to use the class method:
$scope.dashboard = Dashboard.get({ id: 1234 });
Dashboard.update({ id: $scope.dashboard.id }, $scope.dashboard);
Instead is there a way I can call it as an instance method of a particular dashboard?
$scope.dashboard = Dashboard.get({id: 1234 });
$scope.dashboard.update();
Check out the docs.
About halfway down:
The action methods on the class object or instance object can be invoked with the following parameters:
HTTP GET "class" actions: Resource.action([parameters], [success], [error])
non-GET "class" actions: Resource.action([parameters], postData, [success], [error])
non-GET instance actions: instance.$action([parameters], [success], [error])
And an example from their page:
var User = $resource('/user/:userId', {userId:'#id'});
var user = User.get({userId:123}, function() {
user.abc = true;
user.$save();
});
$resource is awesome providing very convenient way to handle web services.
What if GET and POST have to be performed on different URLs?
For example, GET URL is http://localhost/pleaseGethere/:id
and POST URL is http://localhost/pleasePosthere without any parameter
Use 'url' property of [actions] to override the default url.
$resource(url, [paramDefaults], [actions], options);
for example:
$resource('http://localhost/pleaseGethere/:id',{},{
getMethod:{
method:'GET',
isArray:true
}
postMethod:{
url:'http://localhost/pleasePosthere',
method:'POST',
isArray:false
}
}
Usage of Angular $resource: http://docs.angularjs.org/api/ngResource/service/$resource
You should be able to expose the URL as a parameter. I was able to do this:
$provide.factory('twitterResource', [
'$resource',
function($resource) {
return $resource(
'https://:url/:action',
{
url: 'search.twitter.com',
action: 'search.json',
q: '#ThingsYouSayToYourBestFriend',
callback: 'JSON_CALLBACK'
},
{
get: {
method: 'JSONP'
}
}
);
}
]);
Then you can overwrite the URL on your GET call.
The one caveat I found during my REALLY brief testing was that if I included http:// in the URL string, it didn't work. I didn't get an error message. It just did nothing.
If you add the hash with param names into the $resource call:
$resource('localhost/pleaseGethere/:id', {id: '#id'});
Then the :id will be mapped to id param when invoking the function (this will call GET localhost/pleaseGethere/123):
Resource.get({id: 123});
For POST, you simply don't assign the id param:
Resource.post({}, {name: "Joe"});
The proper URL will be called, which is in this case POST localhost/pleaseGethere (the trailing slash is stripped by ngResource).
See http://docs.angularjs.org/api/ngResource.$resource -> Examples -> Credit card resource for more details.
In addition to Iris Wong's answer, I wanted to give an example of having multiple params with multiple methods and actions:
angular
.module('thingApp')
.factory('ThingResource', ['$resource', '$state', returnThing]);
And the resource:
function returnThing($resource, $state) {
var mainUrl = '/api/stuffs/:stuffId/thing'
var params = {stuffId: '#_id', thingMongoId: '#_id', thingNumber: '#_id'}
return $resource(mainUrl, params, {
'save': {
url: '/api/stuffs/:stuffId/thing/:thingMongoId',
method: 'POST',
interceptor: {
responseError: function(e) {
console.warn('Problem making request to backend: ', e)
$state.go('oops')
}
}
},
'get': {
url: '/api/stuffs/:stuffId/thing/:thingMongoId',
method: 'GET',
interceptor: {
responseError: function(e) {
console.warn('Problem making request to backend: ', e)
$state.go('oops')
}
}
},
'assignThing':{
method: 'POST',
url: '/api/stuffs/:stuffId/thing/assign/:thingNumber'
}
});
}
Which gives 3 separate methods:
// POST to http://currnt_base_url/api/stuffs/:stuffId/thing/:thingMongoId
ThingResource.save({
stuffId:'56c3d1c47fe68be29e0f7652',
thingMongoId: '56c3d1c47fe6agwbe29e0f11111'})
// GET to current http://currnt_base_url/api/stuffs/:stuffId/thing/:thingMongoId
ThingResource.get({
stuffId:'56c3d1c47fe68be29e0f7652',
thingMongoId: '56c3d1c47fe6agwbe29e0f11111'})
// POST to http://currnt_base_url/api/stuffs/:stuffId/thing/assign/:thingNumber
ThingResource.assignThing({
stuffId:'56c3d1c47fe68be29e0f7652',
thingNumber: '999998'})
Follow this way:
(function () {
'use strict';
angular
.module("app")
.factory("SomeFactory", SomeFactory);
function SomeFactory($resource) {
var provider = "http://stackoverflow.com/:action/:id";
var params = {"id":"#id"};
var actions = {
"create": {"method": "POST", "params": {"action": "CreateAwesomePost"}},
"read": {"method": "POST", "params": {"action": "ReadSomethingInteresting"}},
"update": {"method": "POST", "params": {"action": "UpdateSomePost"}},
"delete": {"method": "GET", "params": {"action": "DeleteJustForFun"}}
};
return $resource(provider, params, actions);
}
})();
I hope it help! Enjoy!