I have a resource in my API called /foos. I can create a new Foo by making a POST request to this URL.
In the client I use Angular's ngResource to deal with API calls. Insertion is easy:
var newFoo = new Foo({param1: 'value1'});
newFoo.$save();
So far, so good. The API returns the following:
{id: 1, param1: "value1"}
Now, here's the good part. For the sake of simplicity my API allows to specify which related entities should be returned in the response by means of a query string param, with. So:
GET /foos/1?with=relatedEntity
Would return
{id: 1, param1: "value1", relatedEntity: { ... }}
This is also accepted in POST requests. I'd like to create a Foo and have it returned back with some related entities so that I can use them straight away in my app without the need to perform another request:
POST /foos?with=relatedEntity
However, I've been unable to achieve this using standard the ngResource $save() function.
Can this be done at all?
My bad.
Our client extends the base $resource factory and overrides the $save() function, but this implementation was not propagating all the required parameters down the call chain, so no URL params were being sent.
Related
I am trying to implement CRUD using $resource, i am not finding any issues in POST, PUT and GET. But on delete method the params are getting passed as query string.
My service:
service.Assigndepart = $resource(CONFIG.wsurl + '/employee/assign/depart',null, {
update: {
method: 'PUT'
},
remove:{
method: 'DELETE'
}
});
And calling my controller as
Assigndepart.remove(params, function(success), function(error));
my url is passing with query string as ?employee=1234&depart=456.
Can some help on this
See basically if you get into the Html apis in form tag for method type what you will see is only support for get and post method, which indicates that with post and get we can do everything we want all of the others are just good conventions and some code optimizations(like put method).The delete method is just similar to the get method which always includes the parameters as its param there is nothing you can do about it.if you want to remove that you have to use the structure of post or put requests only or you can still use the delete method with some encryption and decryption at both ends i.e. application server and front end.
According to the Angular $resource documentation the action methods without a body need to be invoked with the following parameters:
Resource.action([parameters], postData, [success], [error])
So you are passing your postData as params for your DELETE action. The correct call on your controller will be:
Assigndepart.remove({}, params, function(success), function(error));
I am attempting to implement a sample application with Angular that interacts with a backend REST API using $resource objects. However, the backend system does not generate id's for the resources, so these need to be defined on the objects being created on the client. This causes a problem when invoking the $save method on the new'ed resource because it forces the JSON data to be POSTed to the wrong URL, i.e., it POSTs to:
/resources/employees/1234
rather than:
/resources/employees
I would prefer not to have to drop down to using the low level $http service if I can avoid it.
Does anyone know how I can work around this issue?
Thanks.
This is because of the fact that you configured your $resource constructor in this way, for example:
$resource('resources/employees/:employeeId', {
employeeId: #id
});
That means that when you call methods like $save or $delete etc. on the resource objects made by this constructor, the variable :employeeId in the url will be filled with the value id that exist on the object on which you called the method. To avoid this you have to modify the constructor config so that the url variable does not depend on the object id property.
So I'm trying to AJAX a single solr doc from my results list to a "doc view" view. I'm trying to use AngularJS to AJAX to my view render method and display the doc that way, but I can't seem to get the angular to work and I'm not sure I'm doing things correctly on the Play side either. Would you at least be willing to tell me if what I'm trying to do will work? The Angular error comes from the docText.text(); call. Here is my code:
Angular controller code:
var docText = $resource("http://localhost:9000/views/full-doc-text.html", {
text: {method: 'PUT'}
});
$scope.handleViewText = function(value) {
docText.text({doc: value});
}
Java code:
public static Result viewText() {
JsonNode json = request().body().asJson();
//do stuff here
return ok(viewtext.render(json));
}
route:
GET /views/full-doc-text.html controllers.Application.viewText()
I see three problems with the code above;
1.The definition of docText resource is not correct. if your read the angularjs manual here you'll see that $resource has 4 parameters. First one is resource url, second is parameter defaults, third one is custom actions and forth one is resource options where last three of them are optional. In your code you pass custom actions as the second parameter, which should be the third. And since you don't have any parameters in your resource url second parameter must be null. So first correction is:
var docText = $resource("http://localhost:9000/views/full-doc-text.html", null, {
text: {method: 'PUT'}
});
2.You define your text action's HTTP method as PUT however in your routes file you are handling GET requests for your desired action. You should change your route definition as:
PUT /views/full-doc-text.html controllers.Application.viewText()
3.PUT method is usually used for update operations when implementing a RESTFULL service. In your case you don't seem to be updating anything. So I suggest to use POST method just for convention.
I've really be trying to wrap my head around this as much as possible, but having a very difficult time doing so. Maybe I'm missing the obvious.
Given a typical REST API (with an idempotent update method and a create method):
http://www.domain.com/api/clients GET // returns all clients
http://www.domain.com/api/clients POST // create a new client
http://www.domain.com/api/clients/:id GET // returns single client
http://www.domain.com/api/clients/:id PUT // updates a single client - idempotent
http://www.domain.com/api/clients/:id DELETE // delete single client
If I create a standard resource with the following URL:
Client = $resource("http://www.domain.com/api/clients/:id")
Then I automatically get (where Client is the $resource and client is the returned entity):
Client.get()
Client.query()
Client.save()
client.$save()
client.$remove/delete()
The problem I have is by default there is no PUT method to save (typically used to identify idempotent updates).
Am I misunderstanding something or is this a deficiency in Angular's API? I would have expected the $save() to use a PUT and not a POST. The way it is currently structured, I have to create my own $update() method definition and then rely on the developer not to accidentally use the $save() method.
Am I structuring my API incorrectly? Should the REST API be structured differently?
You can simply specify the method in your resource like :
app.factory('someFactory', ['$resource', function($resource) {
return $resource('/api/:id', {
id: '#id'
}, {
update: {
method: 'PUT'
},
get: {
method: 'GET'
}
});
}]);
but I totally agree with $save being an odd verb for create and not update. This guy does too and it looks like he made a way to dual purpose the save by simply extending the object and checking for an id.
My question is similar but not the same as this one.
Here is my fiddle
I'm working with a public resource. I don't think it is jsonp. (the flag they use is pjson which i think, to them , means pretty json).
If i have the method as JSONP it will call out and return but then i get an invalid label error. If i have the method set as GET i get the OPTIONS error in firebug (which i typically associate with cross-domain violations).
Oddly, my app calls out to other external resources without issue - so i'm not sure how it is getting that done and can't do this. Am I SOL if i have no control over this outside resource?
$scope.serviceDesc = layerRes.get();
It looks like you can make JSONP calls to this service you're using by specifying a callback=JSON_CALLBACK in the url parameters when using the $http service, or in your case the $resource service
Have a look at this example that I've written up: http://plnkr.co/edit/7EE85Mr8bZBUroQTp5A9?p=preview
$http.jsonp('http://services.arcgisonline.com/ArcGIS/rest/services/World_Physical_Map/MapServer/0?f=json&callback=JSON_CALLBACK')
.success(function(data) {
console.log('The data from their server:');
console.log(data);
$scope.worldPhysicalMap = data;
});
Converting this to use $resource shouldn't be much different.