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();
});
Related
I have a angularJS application with an api service defined as follows:
(function ()
{
'use strict';
angular
.module('myApp')
.factory('api', apiService);
/** #ngInject */
function apiService($resource)
{
var api = {};
// Base Url
api.baseUrl = 'http://localhost:37243/';
api.Auth = $resource(api.baseUrl + 'auth/:verb', {}, {
login: {
method: "POST",
params: {
verb: 'credentials'
}
},
logout: {
method: "GET",
params: { verb: 'logout' }
},
getSession: {
method: "GET",
params: { verb: 'session' }
}
});
return api;
}
})();
and I am executing the login method from an Auth service like this:
authService.login = function (user, success, error) {
var apiAuth = new api.Auth();
apiAuth.$login(user).then(
function (response) {
var loginData = response;
authService.getSession();
$rootScope.$broadcast(AUTH_EVENTS.loginSuccess);
success(loginData);
}, function (response) {
$rootScope.$broadcast(AUTH_EVENTS.loginFailed);
error(response);
});
};
The api call is working but it is passing the payload in the query string rather than a data payload. I guess I have $resource configured incorrectly but cannot work out why.
What is being sent:
http://localhost:37243/auth/credentials?password=Password1&username=admin
What I want to be sent:
POST http://localhost:37243/auth/credentials
{password: 'Password1', username: 'admin'}
Any ideas?
I've worked out the problem...
The reason is because I'm instantiating the resource object Auth and then executing the method.
From the ngResource documentation, the method signatures for "non-GET" methods (like mine) are:
non-GET "class" actions: Resource.action([parameters], postData,
[success], [error])
non-GET instance actions: instance.$action([parameters], [success], [error])
So I was running under the second circumstance where there is no postData parameter.
Changing my code to not instantiate the object, as follows, worked:
//the login function
authService.login = function(user, success, error) {
api.Auth.login(null, user).then(
function(response) {
var loginData = response;
authService.getSession();
$rootScope.$broadcast(AUTH_EVENTS.loginSuccess);
success(loginData);
}, function(response) {
$rootScope.$broadcast(AUTH_EVENTS.loginFailed);
error(response);
});
};
For more info see this SO answer (up-voted)
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 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});
}
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.
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)