Query-String support in Ember Router

And hooray for everyone’s participation in these discussions.

One thing I don’t like about my implementation is param order for the model hooks:

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) {}
});

One idea I had is to have an ENV flag, e.g. ENV.NEW_ROUTE_HOOK_ARGUMENT_ORDER, which would change the param order to the slightly more sensible:

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

A warning would appear in the console unless that flag is set, and eventually it would become the default, much like some other ember upgrade strategies I’ve seen in the past. Does this seem like a sensible idea?

I decided this was a good idea, it seems silly to compromise on the API. It’s now implemented in the pull request.

So you all know, this has now been merged into master. I will be making some alterations to the parameter order this evening, but it’s mostly there. Thanks to everyone for your help and feedback!

1 Like

Thanks @alexspeller for the awesome hard work!

Now that this is in master (except for two outstanding pull requests)I need to think of a nice API for queryParams that only affect client side state.

The idea is that if you’re e.g. sorting or filtering on the client side, you don’t want the model hook to be called again and do another round trip to the server. There needs to be some way of specifying this in the query params definition.

Something like:

App.Router.map(function() {
  this.resource('posts', queryParams: ["sort:clientOnly"]);
});

Or

App.Router.map(function() {
  this.resource('posts', clientSideQueryParams: ["sort"]);
});

Both of these are quite ugly. Any thoughts?

I think this is reasonable, but possibly the wrong way round. Rather it seems to me that having a boundQueryParams that calls the model hook and a simple queryParams that doesn’t would be the way to go.

Alex, I’d really like to start using this but I’m still prone to newbie mistakes. Are there any examples that I can refer to so that I can feel my way around this a little more. I’m particularly uncertain of what I need to do to “turn on” the feature which I think is now required for new functionality, right?

Anyway, any pointers to examples would be very helpful.

I have now looked at the pull request and there’s a lot there I hadn’t seen. I think that’s probably enough for me to get started. Of course any other working examples would be accepted with working arms.

Thanks for penning such widely usable functionality. Looking forward to using it.

For the record, I’ve been using queryParams in my application and it drastically simplified my code. Really nice work on this @alexspeller.

This looks very promising!

Currently I would like to make a Google Suggest like functionality in my application. Is there any example on how to perform a search query on a router? There is not such an example?

This is not in 1.2, is there a patch to get it into 1.2 w/o having to use a canary build?

It is possible to generate custom builds with this enabled based on the stable branch (v1.2.0), but it is not generally advisable.

@jasonmit - Feel free to message me privately for the details.

@rwjblue

Yea, that’s what I just ended up doing and just flipping the boolean in features.json

Thanks!

The queryParams API on Canary is going to be changed. Feel free to flip flags but be prepared to update your app when these changes land.

Is there a timeframe? I’m aware of the API changing but it’s a must-have in our current happen so I guess I’ll spend the time rewriting when you iron out the spec.

I’ll probably have something checked into master in the next few days, which would mean it’d be released under 1.4 assuming the API is approved by everyone.

1 Like

But yes, if it’s a must have, you should use what’s on Canary. The transition will probably be pretty simple.

What’s your use case? Are you using queryparams to bind to some value in a controller? Are you using it to initiate transitions?

The use case is to bind values on the controller and to talk to the router to reload the model via filtering params.

Think of it as a report application where there are many properties used for filtering that you want to use to drive the data shown in the grid. There are many options to filter the data and we want to capture that state and make it routeable.

Cool.

The latest thinking is to make controllers the “source of truth” in regards to query params, in that properties can be defined as query param properties on controllers. URL changes to query params will update these properties, and changes to these properties will update the URL. Adding controller query param properties won’t by default cause any route transitions to occur; in the cases where you want transitions, we’re thinking of firing a queryParamsDidChange action on the routes that can be handled to cause a transition. We’re thinking of adding a Route#refresh method that well basically cause an in-place “transition” that’ll refire model hooks that may depend these query params.

Hopefully that’s not too vague; do you think that’d fit your use case decently?

2 Likes