Description
I'm seeing two weird bugs if doing a redirect to the same route with different queryParams in beforeModel
hook:
- If the route is entered via
<LinkTo>
ortransitionTo()
, the query param is not reflected in the URL. - If the route is entered directly on application start, ember throws an error.
The error thrown is this one:
TypeError: Cannot read property 'name' of undefined
at Class._queryParamsFor (https://t95pf.sse.codesandbox.io/assets/vendor.js:35740:59)
at Class.finalizeQueryParamChange (https://t95pf.sse.codesandbox.io/assets/vendor.js:34759:29)
at Class.triggerEvent (https://t95pf.sse.codesandbox.io/assets/vendor.js:36198:27)
at PrivateRouter.triggerEvent (https://t95pf.sse.codesandbox.io/assets/vendor.js:35078:43)
at PrivateRouter.finalizeQueryParamChange (https://t95pf.sse.codesandbox.io/assets/vendor.js:72248:12)
at PrivateRouter.queryParamsTransition (https://t95pf.sse.codesandbox.io/assets/vendor.js:71741:37)
at PrivateRouter.getTransitionByIntent (https://t95pf.sse.codesandbox.io/assets/vendor.js:71810:37)
at PrivateRouter.transitionByIntent (https://t95pf.sse.codesandbox.io/assets/vendor.js:71759:21)
at PrivateRouter.doTransition (https://t95pf.sse.codesandbox.io/assets/vendor.js:71894:19)
at PrivateRouter.transitionTo (https://t95pf.sse.codesandbox.io/assets/vendor.js:72372:19)
It's caused by routeInfos
of transition
being an empty array here: https://github.com/emberjs/ember.js/blob/v3.14.1/packages/%40ember/-internals/routing/lib/system/route.ts#L2523 _queryParamsFor
can't handle that case and throws at this line: https://github.com/emberjs/ember.js/blob/v3.14.1/packages/%40ember/-internals/routing/lib/system/router.ts#L926
For a minimal reproduction use this code:
// app/routes/foo.js
import Route from '@ember/routing/route';
export default Route.extend({
async beforeModel(transition) {
if (!transition.to.queryParams.bar) {
await this.transitionTo('foo', { queryParams: { bar: "1" }});
}
}
});
// app/controllers/foo.js
import Controller from '@ember/controller';
import { inject as service } from '@ember/service';
export default Controller.extend({
router: service(),
queryParams: ['bar'],
});
The current route is logged in template to verify that the query params are available on RouteInfo
object for scenario 1. And they are indeed. They are just not represented in URL.
Both bugs could be fixed by explicitly aborting the transition before doing the redirect:
// app/routes/foo.js
import Route from '@ember/routing/route';
export default Route.extend({
async beforeModel(transition) {
if (!transition.to.queryParams.bar) {
transition.abort();
await this.transitionTo('foo', { queryParams: { bar: "1" }});
}
}
});
But accordingly to documentation transitionTo()
should implicitly abort the transition. It should not be required to do it manually. Also if this is the recommended solution, there should be an assertion if the transition is not aborted before. It should not end with a broken state (URL not reflecting query parameters in URL) neither with throwing a TypeError
.
There are some issues which seem to be related but slightly different:
- transition.abort() does not work for query param only transitions #18568
- Cannot read property 'name' of undefined when trying to set queryParams in beforeModel #17118
- replaceWith / transitionTo doesn't respect query params on beforeModel #14606
- QP only transition in beforeModel of application route throws error #11563
- Query params not updated by transitionTo/replaceWith during active transition #10262
Activity