emberjs/ember.js — pull request #3182 by alexspeller (2013-08-24 06:29:32+00:00)
Title: Initial QueryParams implementation

It's finally here. It works well. There are lots of tests. It makes sense. The API is as nice as possible whilst not introducing any backwards-incompatible changes. It works with all location implementations. There are nice, verbose error messages. It is, in general, super-awesome.

[Live JSFiddle demo](http://jsfiddle.net/alexspeller/K9xUP/4/)

Defining your query params
--------------------------

Query params are baked right into the routes. This is essential so that the router and helpers can know what valid transitions and query parameter states are.

```coffee

App.Router.map ->
@resource 'posts', queryParams: ['sort', 'direction'], ->
@resource 'post', path: "/:id", queryParams: ['showDetails']
```

Model hooks
-----------

Query params are passed into all the relevant model hooks now. The queryParams are passed in as the last
parameter in order to preserve current behaviour in all cases. Only query params that have been registered to apply to the route in the router.map call will be passed in. If no query params are active for this route,
an empty object `{}` is passed in.

```javascript
App.PostsRoute = Ember.Route.extend({
beforeModel: function (transition, queryParams) {},
model: function(params, transition, queryParams) {},
afterModel: function (resolvedModel, transition, queryParams) {},
setupController: function (controller, context, queryParams) {},
renderTemplate: function (controller, context, queryParams) {}
});
```

Transitioning Query Params
-------------------------

`transitionTo` now will accept a final argument, which must be an object with the key `queryParams`.

```javascript
this.transitionTo('post', object, {queryParams: {showDetails: true}});
this.transitionTo('posts', {queryParams: {sort: 'title'}});
this.transitionTo({queryParams: {direction: 'asc'}});
```

You can also use add query params to URL transitions as you would expect:

```javascript
this.transitionTo("/posts/1?sort=date&showDetails=true");
```

linkTo Helper
-----------

The linkTo helper supports queryParams as well.

```handlebars
{{#linkTo 'posts' direction=asc}}Sort{{/linkTo}}
{{#linkTo 'posts' directionBinding=otherDirection}}Sort{{/linkTo}}
```

The linkTo helper now takes into account query parameters when determining its "active" state, and will set the class appropriately. The active state is determined by working out if you clicked on the link, would the query params end up the same? You don't have to supply all of the current, active query params for this to be true.

Stickiness
---------

By default, query params are "sticky". This means that if you are on a url like `/posts?sort=name`, and you executed `transitionTo({queryParams: {direction: 'desc'}})` or clicked `{{#linkTo 'posts' direction=desc}}`, the resulting url will be `/posts?sort=name&direction=desc`. This is true whilst you are linking to a route in the currently active tree.

To clear query params, give a falsy value (but **not** `undefined`), e.g.
`transitionTo({queryParams: {direction: null}})` or `{{#linkTo 'posts' direction=false}}`

Boolean Query params
----

Boolean query params are serialised without the truth value, e.g. `transitionTo('posts', {queryParams: {sort: true}})` would result in the url `/posts?sort`

TODO
----

Query param changes always hit the model hook. This is not always necessary. There should be a way to specify that query params don't affect the model.
Slightly more automatic way to observe controller params and serialise to url