Some notes on problems I'm experiencing with Ember's Query-Params.
I'm trying to create a "global" query-param that exists on controller:application
and sticks around for the whole session.
An example might be http://myapp.com/some/route?locale=es
. The only oddity is that only some users are allowed to set
this parameter; for other users, it's ignored. I started with the following
// app/pods/application/controller.js
export default Ember.Controller.extend({
queryParams: [ 'locale' ],
locale: Ember.computed({
get() { return undefined; },
set(prop, newValue) {
return userCanSetLocale ? newValue : undefined;
}
}
});
Ember is supposed to keep the URL representation (?foo=bar
) and the controller representation
(controller.get('foo')
) in sync. That sync hasn't happened on the first transition. In order to reliably
access this.controllerFor('something').get('foo')
in all transitions, I need to add the following to
my route:application
:
const FixQueryParamsOnBoot = Mixin.create({
// Ember doesn't copy query params from the transition to the
// controller until the end of the transition. Call this to ensure
// they're properly initialized.
beforeModel(transition) {
const controller = this.controllerFor('application');
controller.getWithDefault('queryParams', []).forEach(function(key) {
if (controller.get(key) != null) return;
controller.set(key, transition.queryParams[key]);
});
}
});
// app/pods/applicaton/route.js:
export default Route.extend(FixQueryParamsOnBoot, {
beforeModel() {
initializeSession().then(() => {
return this._super(...arguments);
});
}
});
If I specify
// app/pods/application/route.js
export default Ember.Route.extend({
queryParams: {
foo: { refreshModel: true }
}
});
then I can't use transitionTo('symbolic.route')
or Ember will complain that it can't find enough
dynamic segments. See http://discuss.emberjs.com/t/queryparams-how-to-satisfy-dynamic-segments-for-route/6714
Instead, I have to not mark foo
as refreshModel: true
and instead use a manual this.refresh()
call.
Let's say I have a global query-param (declared on controller:application
). If I have a route that redirects
to another route:
// app/pods/something/route.js
export default Ember.Route.extend({
beforeModel() {
this.transitionTo('something.else');
}
});
then the query-param is lost from the URL when I transition. The smallest solution I've found is
// app/pods/application/route.js
export default Ember.Route.extend({
// Override Ember's default implementation to fetch from the
// controller:
serializeQueryParam(value, key, ...args) {
// Query params on controller:application seem to get obliterated
// on every transitionTo, replaceWith, and link-to call. The problem
// might be the HistoryLocation or our <base> tag, or something else.
// This is the smallest fix, though it won't work with query params
// that use "as" to map the query-param name to a URL param.
value = value || this.controllerFor('application').get(key);
return this._super(value, key, ...args);
}
});