according to the docs i can define custom actions for each resource. This is the REST API resource I was interested in configuring (see postman import link):
http://0.0.0.0:9000/api/properties_by_address
method: POST
post data: raw json:
{
"address" : "%address%"
}
setting up the resource in my services (i called it search, see js equivalent):
window.API_HOST ="http://localhost:9000/api/";
angular.module("app.services", [])
.factory("Properties", [
"$resource"
($resource) ->
$resource API_HOST + "properties/:id", null,
search:
method: 'POST'
url: API_HOST + 'properties_by_address'
params:
hello: 'good world'
address: 'good address'
])
I try to call this in a directive like so (see this for js conversion):
.directive('homeSearch', ['Properties', (properties) ->
restrict: 'AEC'
replace: false
templateUrl: '/partials/home_search.html'
link: (scope, elem, attrs) ->
button = elem.find('.button')
button.bind "click", ->
console.log "address searched" + scope.address
properties.search {}, address: scope.address
return
])
weird stuff happens here.. first of all instead of making the mothod call 'POST' it uses 'OPTIONS' instead.. further.. it only uses the parameters set up in the default definition (ie good world, good address.. instead of the scope.address value.. which i tested to be valid) see the summary of the request/response in this chrome devtools screenshot:
questions:
- how do i make the service use the parameters that I use when i call it?
- how do i specify that it takes the parameters as post JSON data.. rather than appending it to the query string?
First, for resource, you can't default the post body as it would go against the Angular paradigm for a Resource object. Here's a better answer than I could give. Basically, the params attribute will always and only default your query string parameters.
Also, you should define your resource like this:
// Tell $resource that the 'id' property resides within the resource by using '#id'
$resource(API_HOST+ '/properties/:id', {id: '#id'}, {
search: {
url: API_HOST + 'properties_by_address',
method: 'POST'
}
});
To change the request body of your post, you're going to have to call the search function like this:
Properties.search({address: $scope.address, hello: 'good world'}, function(result){
// Do something with the response here
}, function(error) {/* handle error here if you want*/});
As far as the OPTIONS method being used, I have not seen that before. Might it be because of the API that you're requesting from? Although that may be a stretch. You may want to confer with the people that manage your server.
Related
I have searching for decoding my URL substring param having forward slash which sent as %2F instead /
var Report = $resource('api/v1/report/:action/:key', {key:'#key'}, {
getById: {
method: 'GET',
params: {
action: 'abc/source'
}
},
});
I am getting exceptions while i was running some unit tests but however it is working with browser testing.
Error: Unexpected request: GET api/v1/report/abc%2Fsource/raj
How can make this always consider as /?
I also tried using javaScripts decodeURIComponent but it does not seem to work. Any Ideas
Thanks
$resource is correctly converting / to %2F, As it part of URL. Seems you need to change the URL of $resource, It can be overridden.
In resource declaration method declarion override the URL.
url – {string} – action specific url override. The url templating is supported just like for the resource-level urls.
Code
var Report = $resource('api/v1/report/:action/:key', {
key: '#key'
}, {
getById: {
url: 'api/v1/report/:action1/:action2/:key', //Override URL for getById
method: 'GET',
params: {
action1: 'abc',
action2: 'source'
}
},
});
I am learning Angluarjs's $resource. I set a button on HTML for deleting a record from a json file,and hope to delete one record from testForm.json file. Unfortunately, I failed to do so and can't solve the problem.
The codes are here: my Angularjs code
The deleting function in controller codes is shown as follows
$scope.deleteRecord = function () {
var id = 1;
var arecord = new singleResource();
arecord.$get({userId:id},function () {
$log.info(arecord);
arecord.$delete();
});
The HTML part of the deleting function is shown here:
<div class="form-group">
<div class="col-sm-6 col-sm-push-2">
<button type="button" class="btn btn-primary" ng-click="deleteRecord()">Delete information</button>
</div>
</div>
"$scope.deleteRecord" is the function that when clicking the Delete information button, the record with id=1 in json file should be removed. The error says:"DELETE http://localhost:3000/contactInfo 404 (Not Found) :3000/contactInfo:1 ", while the "arecord" is shown as an object in the log "m {email: "333#333", password: 321, method: "Internet", id: 1, $promise: undefined…}", which should be fine.
$http
$http.get('/someUrl', config).then(successCallback, errorCallback);
$http.post('/someUrl', data, config).then(successCallback, errorCallback);
$http is built into Angular, so there’s no need for the extra overhead of loading in an external dependency. $http is good for quick
retrieval of server-side data that doesn’t really need any specific
structure or complex behaviors. It’s probably best injected directly
into your controllers for simplicity’s sake.
$resource
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])
$resouce is good for situations that are slightly more complex than $http. It’s good when you have pretty structured data, but you
plan to do most of your crunching, relationships, and other operations
on the server side before delivering the API response. $resource
doesn’t let you do much once you get the data into your JavaScript
app, so you should deliver it to the app in its final state and make
more REST calls when you need to manipulate or look at it from a
different angle.
Alternatively you could use: restangular https://github.com/mgonto/restangular
Restangular is a perfect option for complex operations on the client side. It lets you easily attach custom behaviors and interact
with your data in much the same way as other model paradigms you’ve
used in the past.
Angularjs guide: https://docs.angularjs.org/api/ng/service/$http#delete
try with the delete method:
$scope.deleteRecord = function () {
var id = 1;
var arecord = new singleResource();
arecord.$delete({userId:id},function () {
$log.info(arecord);
//arecord.$delete();
});
or
$http({
method: 'DELETE',
url: '/someUrl'
}).then(function successCallback(response) {
// this callback will be called asynchronously
// when the response is available
}, function errorCallback(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
I hope it helps.
webApp.factory('userAPIService', ['$resource',
function ($resource) {
return $resource(
"/api/reportconfig/:Id",
{Id: "#Id" },
{
// at some point change methods from GET to POST and DELETE
"update": {method: "PUT"},
"getreport": {'method': 'GET', 'params': { Id:'getReportbyReportID', expire: 'true', cache:'false'}, isArray: true},
"createreport": {'method': 'GET', 'params': { Id:'createreport', expire: 'true', cache:'false'}},
"listreport": {'method': 'GET', 'params': { Id:'listreport', expire: 'true', cache:'false'}, isArray: true},//requre user_uuid
"deletereport": {'method': 'GET', 'params': { Id:'deletereport', expire: 'true', cache:'false'}}
}
);
}]);
The above code get called with the following command
userAPIService.createreport({
'report_config_json': report_config_json, topic_uuid: topic.uuid, report_id: reportID, user_id:userid }, {'Id': 'createreport'})
I'm having a hard time understanding what the userAPIService actually returns when called, an object? what does it return when I call userAPIService.createreport? How/when are the arguments passed to it?
With only the limited information I have above, here is what I believe is taking place in your code:
First, you are creating a factory, which is similar to a service, except you get multiple instances as opposed to a singleton (a one-time creation that every module can get via injection)
When you use the userAPIService factory in your code, you are being returned a function (which in this scenario could act like a constructor.) I can't tell without seeing the context of your use of userAPIService, but I would assume you are creating a local variable called 'userAPIService' which is being initialized to the results of a call to userAPIService().
At this point you have an instance of a userAPIService which appears to just be an data retrieval service (not to be confused with an Angular Service, which is a singleton)
your call to userAPIService.createreport() will initially return an empty object or array (noted in the docs at the bottom of this answer.) it will then make the specified $http call to the URL (from $resource definition) via the Method (from the $resource definition) and attempt to retrieve the data you are looking for. Once it has completed that request, it will then populate the reference that was just created with the actual data returned.
Since your factory creates custom actions to be taken via $resource we will look at that definition to determine what will take place when you call .createreport():
"createreport": {'method': 'GET', 'params': { Id:'createreport', expire: 'true', cache:'false'}}
This line tells $resource how to handle requests using the createreport() method. It says that when this method is called, it will make a request to the $resource object's URL via GET. It will pass default values of expire:true and cache:false as well as Id:'createreport' which will be used to populate the URL (Unless an Id is specified in your method call - which it is), since it requested an Id object via :Id at the end.
Now, when you made the actual method call, you specified two objects to pass to the $resource request, the first will then be used to basically override the default parameter values that were specified when you create the $resource method. The second will be passed as headers along with the $http request that $resource will then make.
For even more information, I would highly recommend that you read the documentation: https://docs.angularjs.org/api/ngResource/service/$resource
I have a angular service which has custom methods like this
appServices.factory('RuleSets', ['$resource',
function($resource){
return $resource('', {}, {
query: {
method:'GET',
isArray:true,
url: '../data/routing-ruleset-:ruleSetId.json'
},
unschedule: {
method: 'POST',
url: '../data/unschedule:ruleSetId.json'
},
schedule: {
method: 'POST',
params: {ruleSetId: ':ruleSetId', date: ':date'},
url: '../data/schedule.json'
}
});
}]);
I am having issues posting data using my custom methods
RuleSets.unschedule({ruleSetId: ruleSetId});
and
RuleSets.schedule({date: $scope.formattedDate, ruleSetId: $scope.selectedRuleSet})
The behavior i see int he former is that the ruleSetId url parameter does not get populated if it is a POST request. In the latter, I do not know how to populate the request parameters if it is a post request (I am aware the code written is incorrect), as what I have tried in my services function does not work. I would also like to send data as part of the request to 'schedule'. I have seen how I can do this by say doing this
var ruleSets = new RuleSets();
ruleSets.id = $scope.selectedRuleSet
ruleSets.$save();
but how do I do it with a custom method?
Should I rather be using $http or not so many custom methods. I like the structure that custom methods provides, so i'd like to keep it like that if possible.
Currently I have a resource like so:
return $resource(usersUrl, {}, {
//The data model is loaded via a GET request to the app
query: {method: 'GET', params: {}, isArray: false},
putupdate: {method: 'PUT', params:{}}
});
Now I would like to put some JSON that looks like:
{"providerid":"userpass","firstname":"t","lastname":"b","fullname":"t b","email":"emailaddress,"avatarurl":"http:/.....","passwordset":true}
Anyway as you can see it doesn't have a top level name, if I pass this information in as a parameter to the resource a name is appended to the json like:
myparam:{"providerid":"userpass","firstname":"t","lastname":"b","fullname":"t b","email":"emailaddress,"avatarurl":"http:/.....","passwordset":true}
Is there a away of preventing this from happening as the server side doesn't like it?
Thanks
Tom
From your question it sounds like you are trying to use $resource to post some arbitrary json data. If this data is not a Resource() you should simply use $http.
$http.put(theUrl, theJsonData);
If it is actually a Resource() you can just call the method you declared when building your resource.
myResource.putupdate();