Reputation: 4475
I followed the Query Params guide (http://guides.emberjs.com/v1.11.0/routing/query-params/) and it worked great. Specifically, refreshing the model did exactly what I wanted.
I'm moving the filter to the json-api spec and filtering takes place in a filter
object. So rather than:
http://localhost:3000/accounts?id=1
The server responds to:
http://localhost:3000/accounts?filter[id]=1
I tried to get the query params to work refreshing the model based on an object, but it doesn't seem to update.
// app/controllers/accounts/index.js
import Ember from 'ember';
export default Ember.Controller.extend({
queryParams: ['filter', 'sort'],
filter: {},
sort: '-id'
});
// app/routes/accounts/index.js
import Ember from 'ember';
export default Ember.Route.extend({
queryParams: {
filter: { refreshModel: true },
sort: { refreshModel: true }
},
model: function(params) {
return this.store.find('account', params);
},
});
// template
<th>{{input type="text" placeholder="ID" value=filter.id}}</th>
Is it possible to have query params work with an object?
Upvotes: 4
Views: 1543
Reputation: 3313
I know this is a bit late but you can use this workaround to allow for objects with query params. It's pretty easy to get working and so far I haven't found any issues with it.
I ran into the same problem when building an Ember app on top of my JSON API (http://jsonapi.org/).
The JSON API specification provides recommended syntax for both paging and filtering that requires object based query params.
For paging it suggests syntax like this:
/books?page[size]=100&page[number]=1
and for filtering it suggest syntax like this:
/books?filter[author]=Bob
While Ember.js Query Params (as of Ember v2.1) do not support this out of the box it is fairly simple to get working. In your controller you should map a controller property to the query param "object" as a string.
So for example, in the above "filter" example you would map a controller property called filterByAuthorValue
to the query param filter[author]
.
The code to do this would look like this:
export default Ember.Controller.extend({
queryParams: ['sort',{
filterByAuthorValue: 'filter[author]'
}],
sort: '',
filterByAuthorValue: ''
});
Note in the example above I also have a query param called sort (which also follows JSON API recommendations but doesn't require an object). For more information on mapping a controller property to a query param see this section of the official Ember.js guide:
Once you have the query param created you then need to handle the query param in your router. First, the router should force the model to be refreshed when the controller property filterByAuthor
changes:
export default Ember.Route.extend({
queryParams: {
sort: {
refreshModel: true
},
filterByAuthor:{
refreshModel: true
}
}
});
Finally, you now need to translate the controller property filterByAuthor
into an actual object when you load the model in the router's model
method and assign the value from the controller property filterByAuthor
. The full router code would then look like:
export default Ember.Route.extend({
queryParams: {
sort: {
refreshModel: true
},
filterByAuthor:{
refreshModel: true
}
},
model: function(params){
// The params value for filtering the entity name
if(params.filterByAuthor){
params.filter = {};
params.filter['author'] = params.filterByAuthor;
delete params.filterByAuthor;
}
return this.store.query('book', params);
},
});
Settings things up like this allows for an object based query param to be used with Ember and thus follow the JSON API recommendations.
The above has been tested with the following versions:
Ember : 2.1.0
Ember Data : 2.1.0
jQuery : 1.11.3
Upvotes: 1
Reputation: 5560
This answer is as of Ember version 1.13.0-beta.1+canary
.
The short answer: No. Query params will not work with an object.
The long answer:
As of now, a private function named _serializeQueryParams
in the Router
serializes the queryParams
.
_serializeQueryParams(targetRouteName, queryParams) {
var groupedByUrlKey = {};
forEachQueryParam(this, targetRouteName, queryParams, function(key, value, qp) {
var urlKey = qp.urlKey;
if (!groupedByUrlKey[urlKey]) {
groupedByUrlKey[urlKey] = [];
}
groupedByUrlKey[urlKey].push({
qp: qp,
value: value
});
delete queryParams[key];
});
for (var key in groupedByUrlKey) {
var qps = groupedByUrlKey[key];
var qp = qps[0].qp;
queryParams[qp.urlKey] = qp.route.serializeQueryParam(qps[0].value, qp.urlKey, qp.type);
}
},
qp.urlKey
would evaluate to 'filter'
in your example, and object would be serialized as 'object [Object]'
. Even though you could override the serializeQueryParam
method in your route, that wouldn't help because the queryParam
key would still be 'filter'
, and you'd need it to be 'filter%5Bid%5D'
Based on this comment in the Ember Discussion Forum, it sounds like object query params are unlikely, and you'd be better off just flattening and unflattening the filtered fields.
Upvotes: 4