The Problem:
I have code to set up a $resource that seems to compile without error:
var ReportsRest = $resource('/reports/:reportId', {reportId: '#id'});
ReportsRest.get({id: 123});
but when that code actually executes the request url that is generated looks like this:
GET http://localhost:5523/reports?id=123 404 (Not Found)
The id is not being parsed and dynamically loaded into the URI. Is there something that I am missing?
Plunkr
http://plnkr.co/edit/3ikqMsnDI9r9LThaQLf3?p=preview
Try this:
var ReportsRest = $resource('/reports/:reportId', {reportId: '#id'});
ReportsRest.get({reportId: 123});
Under $resource Usage, there is this block of text.
paramDefaults
Default values for url parameters. These can be overridden in actions methods. If any of the parameter value is a function, it will be executed every time when a param value needs to be obtained for a request (unless the param was overridden).
Each key value in the parameter object is first bound to url template if present and then any excess keys are appended to the url search query after the ?.
Given a template /path/:verb and parameter {verb:'greet', salutation:'Hello'} results in URL /path/greet?salutation=Hello.
If the parameter value is prefixed with # then the value for that parameter will be extracted from the corresponding property on the data object (provided when calling an action method). For example, if the defaultParam object is {someParam: '#someProp'} then the value of someParam will be data.someProp.
To summarize, the object you pass in needs to use the key of your paramDefaults object to get the value. That value replaces the same :key text in your URL pattern. Any value in the paramDefaults object that is prefixed with an # will be set on the returned model data as a property named whatever follows the #.
var ReportsRest = $resource('/reports/:reportId', {reportId: '#id'});
ReportsRest.get({
reportId: 123,
other: 123
}, function(data) { /* ... */ });
This makes a request to /reports/123?other=123. data, in the callback, looks like { id: 123 }.
Related
I'am trying to get paramter from url like that:
index.html#!/forum/page?1-something
the number that what i'am trying to get
both $location.url(); and $location.absUrl(); get the whole url
do I have to use split and how to do that?
Using $location.search() you can get all query parameters.
by iterating an object you can get all key and value as well.
I used to iterate object using for-in loop. here $location.search() is an object itself so you can iterate it as:
for(let key in $location.search()){
console.log("key: "+key+" value: "+$location.search()[key]);
}
we can also append query parameters using $location.search() by just passing parameters to it. this can be done as:
let obj = {site:'stack overflow', exp: 'happy coding'}
and this obj object can be passed to $location.search() as:
$location.search(obj);
EC2Restangular.setBaseUrl('localhost:9000/');
EC2Restangular.setDefaultRequestParams({
"Id": ID
});
Is there any way to remove default query params from baseUrl in Restangular?
To remove the parameters you can just pass an empty object:
EC2Restangular.setDefaultRequestParams({});
If you want to remove the request parameters from a single request, you can add the empty object to the method call like so:
Restangular.all("widget").getList({})
Update: To remove a specific paramter from the default parameter set is a little trickier.
We can grab the parameter list from the Restangular object, and then use that to remove the parameter we don't need, and then use that new parameter object to pass to the new request:
var params = Restangular.all("projects").reqParams;
delete params['parameterNameYouWantToRemove'];
var projects = Restangular.all("projects").getList(params);
here's the relevant snippet of code:
$scope.submit = function() {
console.log(this);
weekly_habits = $resource('/api/users/:user_id/weekly_habits/:id/', {user_id: '#user'});
entry = weekly_habits.save({name: $scope.newAccomp, count: 0});
$scope.accomplishments.unshift(entry);
$scope.newAccomp = '';
}
my error is that no route matches /api/users/weekly_habits... My project is built in rails and I don't understand what this line means {user_id: '#user'}. Where is this #user object supposed to be? It would be much appreciated if someone explained what's going on here.
Thanks!
From the documentation:
If the parameter value is prefixed with # then the value of that parameter is extracted from the data object (useful for non-GET operations).
And later on they have an example
var User = $resource('/user/:userId', {userId:'#id'});
So the second argument to the resource service are the default parameters. In this case, by default, the userId will be extracted from the resource object you call a method on.
Previously I had an example of a GET operation, which doesn't really make sense in this case. But imagine you were doing a POST ($save) request with a data object. Angular would automatically extract the userId from the data object and inject it into the URL for you. You don't have to manually specify the value for the URL.
More info can be found on the doc page.
http://docs.angularjs.org/api/ngResource.$resource
Quoting the documentation: "If the parameter value is prefixed with # then the value of that parameter is extracted from the data object (useful for non-GET operations)."
The '#user' tells Angular to extract the value of user_id from the 'user' property of the object. So if you call .save() on an object that has an 'user' property of 'abc123', then the :user_id in your URL will be replaced with 'abc123'.
from the documentation (http://docs.angularjs.org/api/ngResource.$resource):
$resource(url[, paramDefaults][, actions]);
paramDefaults(optional) – {Object=} – Default values for url parameters.
...
If the parameter value is prefixed with # then the value of that parameter is extracted from the data object.
The question is what data object do they refer to? How to use this feature?
lets say you have a resource like this:
var User = $resource('/user/:userId', {userId:'#id'});
var user = User.get({userId:123});
It means that the value of :userId in your url will be replaced with the id property from the user object when that property is required.
So when is it required? Its required when you are doing something to an existing user, like geting one, updating one. It is not required when you create a user.
In most cases, you will want to have at least one param prefixed with # in your REST url that resource uses (probably the object id). If you dont have one, that means that in order for you to save an instance of an object, you dont need to know anything about where its stored. This implies that its a singleton object. Maybe like a settings object.
Here is your long awaited example:
var User = $resource('/user/:userId/:dogName', {userId:'#id', dogName:#dog});
User.get({userId:123, dog:'Matt'}, function() { .. })
will produce the request: GET /user/123/Matt
For example, say I have a server API for loading people that handles requests like this: GET /people/?id=101,329,27
I'd like to build a Store (probably a custom class that extends Ext.data.Store) which--assuming it has a list of people IDs--causes the proxy to make a request like the one shown above so that the returned data is only for that subset of persons.
I saw the documentation regarding remote filtering, but my concern is that to use it I would first need to call store.load() which would load all persons, then call filter() to do remote filtering. I'd like to just load the subset of persons the first time.
Thanks for any advice!
Found a solution (although still open to hearing other ideas).
First, you can call a store's load() function with a config object that will be passed to an operation. The API docs for Ext.data.Operation make it clear that one of the config options is for an array of Filter objects, so you can do this:
var idFilter = Ext.create('Ext.util.Filter', {
property: 'id',
value: '100,200,300'
});
myStore.load({
filters: [ idFilter ]
});
This results in a request where the URL querystring contains ?filter=[{"property"%3Aid%2C"value"%3A100,200,300}] (in other words, a URL-encoded version of [{ property: 'id', value: '100,200,300'}]).
You can also just call myStore.filter('id', '100,200,300') without having called .load() first. Assuming you have remoteFilter=true in your store, this will make a request with the same query params shown agove.
Sidenote: you can change the keyword used for 'filter' by configuring the 'filterParam' config option for the proxy. For example, if filterParam=q, then the querystring shown above changes to: ?q=[{"property"%3Aid%2C"value"%3A100,200,300}]
Second, you can control "structure" of the filter in the querystring. In my case, I didn't want something like filter={JSON}, as shown above. I wanted a querystring that looked like this:?id=100,200,300
For this I needed to extend a proxy and override the default getParams() function:
Ext.define('myapp.MyRestProxy', {
extend: 'Ext.data.proxy.Rest',
/**
* Override the default getParams() function inherited from Ext.data.proxy.Server.
*
* Note that the object returned by this function will eventually be used by
* Ext.data.Connection.setOptions() to include these parameters via URL
* querystring (if the request is GET) or via HTTP POST body. In either case,
* the object will be converted into one, big, URL-encoded querystring in
* Ext.data.Connection.setOptions() by a call to Ext.Object.toQueryString.
*
* #param {Ext.data.Operation} operation
* #return {Object}
* where keys are request parameter names mapped to values
*/
getParams: function(operation) {
// First call our parent's getParams() function to get a default array
// of parameters (for more info see http://bit.ly/vq4OOl).
var paramsArr = this.callParent(arguments),
paramName,
length;
// If the operation has filters, we'll customize the params array before
// returning it.
if( operation.filters ) {
// Delete whatever filter param the parent getParams() function made
// so that it won't show up in the request querystring.
delete paramsArr[this.filterParam];
// Iterate over array of Ext.util.Filter instances and add each
// filter name/value pair to the array of request params.
for (var i = 0; i < operation.filters.length; i++) {
queryParamName = operation.filters[i].property;
// If one of the query parameter names (from the filter) conflicts
// with an existing parameter name set by the default getParams()
// function, throw an error; this is unacceptable and could cause
// problems that would be hard to debug, otherwise.
if( paramsArr[ queryParamName ] ) {
throw new Error('The operation already has a parameter named "'+paramName+'"');
}
paramsArr[ queryParamName ] = operation.filters[i].value;
}
}
return paramsArr;
}
});
You can also get your Model object to load a record of itself. From a controller you can do:
this.getRequestModel().load(requestID,{ //load from server (async)
success: function(record, operation) {
.....
}
}
where Request is a model class and requestID is an ID to look up. In this scenario Model object needs to define the proxy too:
proxy: {
type: 'ajax',
reader: {
type:'json',
root: 'data'
},
api: {
create : 'request/create.json', //does not persist
read : 'request/show.json'
}
}