It's amazing, but not good enough.
Consider:
App.PeopleController = Ember.ArrayController.extend({
queryParams: ['page'],
page: 1
});
Here's what's wrong with the above:
- As the url changes,
page
will become a string (e.g. "2", "3", etc), so you have to do a lot ofparseInt
ing if you need it to be treated as a number, which is obviously annoying. page
property is annoyingly sticky; if youlink-to 'people'
and don't specify QP props in thequery-params
sexpr, the first transition into it will use the default value of 1, but if you change the value ofpage
to '2', navigate away, and click that samelink-to
to get back into 'people',page
stickily retains its value of '2' on the grounds thatlink-to
doesn't specify any QP values to override. This is very bizarre, see a more detailed explanation here- Having all this stuff on controllers contradicts our goal of getting the lazy-loading of routes/controllers/templates/sections of your app.
App.PeopleRoute = Ember.Route.extend({
queryParams: {
peoplePage: {
defaultValue: 1,
// default is false; `replace: true` means that when a controller
// changes `queryParams.peoplePage`, the URL will be updated
// via replaceState rather than the default pushState.
// (fwiw: this mimics the existing api of `link-to 'people' replace=true`)
replace: true,
// default is false; this opts into a full transition when
// this QP changes.
refreshModel: true
}
}
});
App.PeopleController = Ember.ArrayController.extend({
// This is how controllers can pick a more appropriate
// name/interface for a query param prop; the router
// knows it as its url-serialized key `peoplePage`,
// but the PeopleController can just call it `page`
page: Ember.computed.alias('queryParams.peoplePage')
});
Here's how this fixes the above concerns:
- When the url changes to
?peoplePage=123
, we can infer from the default value to deserialize into a number, soPeopleController
seesqueryParams.peoplePage
as123
rather than"123"
. - Things are appropriately less sticky; if you link to a route without
specifying a QP value (via
query-params
sexpr), and there's no serialized key-value pair in the URL already, then clicking that link will 1) not even bother serializing anything into the final URL for that QP, 2) the controller will seequeryParams.peoplePage
as thedefaultValue
specified, ornull
if none specified. link-to
won't require eager Controller initialization (or prototype hacks); if you saylink-to 'people' (query-params lol="wat")
, it'll serialize an href of "/people?lol=wat" even if that qp is totally unused (thereafter, if you click a link elsewhere, the lol=wat will disappear from the url unless someone claims it).
Other implications
link-to
will have to specify Route-level query param keys, rather than the present day of specifying property names of controllers in destination route hierarchies.
I really like the defaultValue proposal as I have been unable to keep a clean url with the canary version. As manuelmitasch mentions I do rely on the sticky behavior as I have a list filtered by query params and also a map filtered by the same query params. When the user configures the list the way they want and then link-to to the map and back the params need to persist.