diff --git a/packages/@ember/-internals/routing/lib/system/route.ts b/packages/@ember/-internals/routing/lib/system/route.ts index 77f85a3cb4b..0411715f2b5 100644 --- a/packages/@ember/-internals/routing/lib/system/route.ts +++ b/packages/@ember/-internals/routing/lib/system/route.ts @@ -1935,7 +1935,7 @@ interface PartialRenderOptions { model?: {}; } -function getFullQueryParams(router: EmberRouter, state: TransitionState) { +export function getFullQueryParams(router: EmberRouter, state: TransitionState) { if (state['fullQueryParams']) { return state['fullQueryParams']; } diff --git a/packages/@ember/-internals/routing/lib/system/router.ts b/packages/@ember/-internals/routing/lib/system/router.ts index 8e08c6ca085..871c077c303 100644 --- a/packages/@ember/-internals/routing/lib/system/router.ts +++ b/packages/@ember/-internals/routing/lib/system/router.ts @@ -14,6 +14,7 @@ import { calculateCacheKey, extractRouteArgs, getActiveTargetName, resemblesURL import DSL from './dsl'; import Route, { defaultSerialize, + getFullQueryParams, hasDefaultSerialize, RenderOptions, ROUTE_CONNECTIONS, @@ -28,7 +29,6 @@ import { MatchCallback } from 'route-recognizer'; import Router, { InternalRouteInfo, logAbort, - QUERY_PARAMS_SYMBOL, STATE_SYMBOL, Transition, TransitionError, @@ -861,7 +861,7 @@ class EmberRouter extends EmberObject { let unchangedQPs = {}; let qpUpdates = this._qpUpdates; - let params = this._routerMicrolib.activeTransition[QUERY_PARAMS_SYMBOL]; + let params = getFullQueryParams(this, this._routerMicrolib.activeTransition[STATE_SYMBOL]); for (let key in params) { if (!qpUpdates.has(key)) { unchangedQPs[key] = params[key]; diff --git a/packages/ember/tests/routing/query_params_test.js b/packages/ember/tests/routing/query_params_test.js index b73a3ea4a72..74071df660d 100644 --- a/packages/ember/tests/routing/query_params_test.js +++ b/packages/ember/tests/routing/query_params_test.js @@ -137,6 +137,55 @@ moduleFor( }); } + ['@test Calling transitionTo does not serialize query params already serialized on the activeTransition']( + assert + ) { + assert.expect(3); + + this.router.map(function () { + this.route('parent', function () { + this.route('child'); + this.route('sibling'); + }); + }); + + this.add( + 'route:parent.child', + Route.extend({ + afterModel() { + this.transitionTo('parent.sibling'); + }, + }) + ); + + this.add( + 'controller:parent', + Controller.extend({ + queryParams: ['array', 'string'], + array: [], + string: '', + }) + ); + + // `/parent/child?array=["one",2]&string=hello` + return this.visit('/parent/child?array=%5B%22one%22%2C2%5D&string=hello').then(() => { + this.assertCurrentPath( + '/parent/sibling?array=%5B%22one%22%2C2%5D&string=hello', + 'redirected to the sibling route, instead of child route' + ); + assert.equal( + this.getController('parent').get('string'), + 'hello', + 'controller has value from the active transition' + ); + assert.deepEqual( + this.getController('parent').get('array'), + ['one', 2], + 'controller has value from the active transition' + ); + }); + } + async ['@test Single query params can be set on the controller and reflected in the url']( assert ) {