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
Related
I have a factory:
.factory('CompanyRolesResource', function($resource, FdConfig) {
return $resource(FdConfig.routes.companyRoles);
})
And I have a function that use this factory:
ctrl.saveCompanyRole = function(companyRole) {
return CompanyRolesResource.save({}, companyRole).$promise.then(function (response) {
console.log(response)
});
};
In Chrome DevTools I see that response is data like {status: 200, data: {...}}. But in console.log I just see:
Resource
$promise: Promise
$$state: Object
__proto__: Object
$resolved: true
Where is my data? I can't find it also inside of $promise and $$state.
UPD:
I get right response when I use this way:
$http({
url: FdConfig.routes.companyRoles,
method: "POST",
data: companyRole
}).then(function (response) {
console.log(response.data);
});
But my console.log(response) in factory returns undefined.
You can't access your data from $resource directly as it is retrieved from server asynchronously. This means that your data isn't yet loaded when you try to access it. What you need to do is to supply callback for $resource action.
Starting from Angular 1.2, $resource provides you $promise for each action which you can use to retrieve your data when it's loaded:
CompanyRolesResource.save({}, companyRole).$promise.then(function (response) {
// do whatever you want with your response.data here
});
Resource is your data object. When you use $resource, you don't get the response as (status, data, headers, config) Object. You will directly get the response (your expected response data)
It is important to realize that invoking a $resource object method immediately returns an empty reference (object or array depending on isArray). Once the data is returned from the server the existing reference is populated with the actual data.
Under the hood, the ngResource API uses angular.copy to copy the server data to the empty reference. If the data is not a JavaScript object, nothing will be copied.
In the case of the .save action method, if an array is returned, a $resource:badcfg error will be thrown.
Error: $resource:badcfg
Response does not match configured parameter
Description
This error occurs when the $resource service expects a response that can be deserialized as an array but receives an object, or vice versa. By default, all resource actions expect objects, except query which expects arrays.
To resolve this error, make sure your $resource configuration matches the actual format of the data returned from the server.
For more information, see the $resource API reference documentation.
— AngularJS $resource:badcfg Error Reference
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.
I am trying to send a get request to my rails backend using angular. So what am looking for is the request like this
Parameters: {"location"=>"london", "q"=>{"price_gteq":"33333", "price_lteq":"7777"}}
So in my app.js I tried below code to send the request with the parameters. I am now getting unexpected / and the second nested parameter is not showing aswell as seen below.
$http({
url: "/search.json",
method: "GET",
params: {location: $scope.searchLocation, q: {price_gteq: $scope.min_price, price_lteq: $scope.max_price} }
})
This is what i get when I try like above
Parameters: {"location"=>"london", "q"=>"{\"price_gteq\":\"33333\"}"}
Could someone tell me what am doing wrong here??
By default angular uses $httpParamSerializer which actually can handle nested parameters. Check if your $http uses this service. If for some reason it doesn't work, you can write own paramSerializer and pass it into $http configuration object.
Also check if price_lteq present at the moment, when you send request.
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.
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();