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});
}
Related
I have a order resource that looks like so.
.factory('Order', order)
order.$inject = ['$resource', "ApiEndpoint"];
function order($resource, ApiEndpoint) {
return $resource(ApiEndpoint.url + 'orders.json', {}, {
create: {method: 'POST', url: ApiEndpoint.url + 'orders.json'},
update: {method: 'PUT'},
edit: {method: 'GET', url: ApiEndpoint.url + 'orders/edit.json'},
remove_item: {method: 'GET', url: ApiEndpoint.url + 'orders/remove_item.json'},
});
}
When I run Order.update like so
var params = {
order: {
line_items_attributes: {0: {quantity: 2, id: 1}}
},
order_id: 3
};
Order.update(params, function (resp, respHeaders) {
console.log("response headers", respHeaders());
console.log("change quantity resp", resp);
})
I also tried this:
Order.update({}, params, function (resp, respHeaders) {
console.log("response headers", respHeaders());
console.log("change quantity resp", resp);
})
The params sent to the server end up being inside the URL. For example this was one of the urls the server received
path="/api/mobile/orders.json?order=%7B%22line_items_attributes%22:%7B%220%22:%7B%22quantity%22:8,%22id%22:356265%7D%7D%7D"
I should also note that the method being received by the server is an OPTIONS request. The server has been set up to handle this.
Since I'm sending a PUT request why is $resource delivering the params via the URL and not part of the payload?
from the docs:
non-GET "class" actions: Resource.action([parameters], postData, [success], [error])
the payload is the second argument, so try with this code
var params = {
order: {
line_items_attributes: {0: {quantity: 2, id: 1}}
},
order_id: 3
};
Order.update({}, params, function (resp, respHeaders) {
console.log("response headers", respHeaders());
console.log("change quantity resp", resp);
})
just add an empty object as first parameter to the update method.
have also a look to he section related to custom put requests
If you are updating an order then you should speficy the order id so that service can now which order is going to be updated
function order($resource, ApiEndpoint) {
return $resource(ApiEndpoint.url + 'orders.json/:orderid', {}, {
create: {method: 'POST', url: ApiEndpoint.url + 'orders.json'},
update: {method: 'PUT',params : {orderid : '#order_id'},
edit: {method: 'GET', url: ApiEndpoint.url + 'orders/edit.json'},
remove_item: {method: 'GET', url: ApiEndpoint.url + 'orders/remove_item.json'},
});
}
and then your call
Order.update(params, function (resp, respHeaders) {
console.log("response headers", respHeaders());
console.log("change quantity resp", resp);
})
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();
});
I noticed that although I specify "post" on my ngResource factory, it is passing parameters as GET.
Example of a user factory:
myApp.factory('facUser',['$resource', function ($resource) {
return $resource('/api/User/:route', {}, {
EditUser: { method: 'POST', isArray: true, params: { route: "EditUser", cid: '#cid', objEditUser: '#objEditUser' } }
})
}]);
And this is the call to edit the user:
$scope.Edited_User = facUser.EditUser({
cid: $stateParams.company_id, objEditUser: TempUserInfo
}, function success(data, status, headers) {
console.log(data);
}, function err(data, status, headers, config) {
});
Thus, when I call that, for some reason I see all my values being passed on the header of the API as if it was a GET.
I am having trouble figuring out how to use $save() or how to post/put this as form.
The params keyword will resolve any route variable and the rest will be in the request query.
To send values in the request body you can do:
var user = new User( {
cid: $stateParams.company_id,
objEditUser: TempUserInfo
}) ;
user.$EditUser();
And change your resource to be something like:
$resource('/api/User/:route', {}, {
EditUser: { method: 'POST', isArray: true, params: { route: "EditUser" } }
})
}]);
myApp.factory('facUser',['$resource', function ($resource) {
return $resource('/api/User/:route', {}, {
EditUser: { method: 'POST', isArray: true, params: { route: '#route'} }
})
}]);
And then...
$scope.Edited_User = facUser.EditUser({
route: "EditUser"
}, {cid: $stateParams.company_id, objEditUser: TempUserInfo}, function success(data, status, headers) {
console.log(data);
}, function err(data, status, headers, config) {
});
Essentially the first part is parameters.
The second part is post values.
I was wondering how can I set the isArray parameter in the resource, because sometimes I want it to be true and sometimes false
Here is my resource factory code
dummyServices.factory('Dummy', ['$resource',
function ($resource) {
return $resource('http://dummyServer/dummyApp/dummyREST/:methodName', {}, {
query: {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
isArray: false // <-- isArray: someParameter ???
}
});
}]);
I use it like this:
$scope.myDummyObj = Dummy.query(
{
methodName: 'dummyMethod'
},
myDummyArgument
);
How can I set isArray from my Dummy.query call?
As you might already know, $resource never intended to be a replacement for a more powerful $http service, and, as such, the authors simply didn't bother exposing a more powerful and configurable API.
That said, the only way to configure the resource on run-time is to wrap it in it's own custom factory. But that just makes things uglier, IMO.
PLUNKER
app.factory('Dummy', [
'$resource',
function ($resource) {
return function(config){
return $resource('http://dummyServer/dummyApp/dummyREST/:methodName', {}, {
query: angular.extend({
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
isArray: false // <-- isArray: someParameter ???
}, config)
});
};
}
]);
Controller:
$scope.myDummyObj = Dummy({isArray: true, method: 'GET'})
.query({methodName: 'dummyMethod'});
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)