diff --git a/package.json b/package.json
index 11ca987744b..6cd30a5ad77 100644
--- a/package.json
+++ b/package.json
@@ -137,7 +137,7 @@
"rollup-plugin-commonjs": "^9.3.4",
"rollup-plugin-node-resolve": "^4.2.4",
"route-recognizer": "^0.3.4",
- "router_js": "^7.1.0",
+ "router_js": "^7.1.1",
"rsvp": "^4.8.5",
"serve-static": "^1.14.1",
"simple-dom": "^1.4.0",
diff --git a/packages/@ember/-internals/glimmer/tests/integration/components/link-to/query-params-angle-test.js b/packages/@ember/-internals/glimmer/tests/integration/components/link-to/query-params-angle-test.js
index 3fd18b88771..8e72e7e3e24 100644
--- a/packages/@ember/-internals/glimmer/tests/integration/components/link-to/query-params-angle-test.js
+++ b/packages/@ember/-internals/glimmer/tests/integration/components/link-to/query-params-angle-test.js
@@ -879,5 +879,45 @@ moduleFor(
this.shouldBeActive(assert, '#foos-link');
});
}
+
+ ['@test the component with dynamic segment and loading route should preserve query parameters'](
+ assert
+ ) {
+ this.router.map(function () {
+ this.route('foo', { path: ':foo' }, function () {
+ this.route('bar', function () {
+ this.route('baz');
+ });
+ });
+ });
+
+ this.addTemplate('foo.bar', `Baz`);
+
+ this.addTemplate('foo.bar.loading', 'Loading');
+
+ this.add(
+ 'controller:foo.bar',
+ Controller.extend({
+ queryParams: ['qux'],
+ qux: null,
+ })
+ );
+
+ this.add(
+ 'route:foo.bar.baz',
+ Route.extend({
+ model() {
+ return new RSVP.Promise((resolve) => {
+ setTimeout(resolve, 1);
+ });
+ },
+ })
+ );
+
+ return this.visit('/foo/bar/baz?qux=abc').then(() => {
+ let bazLink = this.$('#baz-link');
+ assert.equal(bazLink.attr('href'), '/foo/bar/baz?qux=abc');
+ });
+ }
}
);
diff --git a/packages/@ember/-internals/glimmer/tests/integration/components/link-to/query-params-curly-test.js b/packages/@ember/-internals/glimmer/tests/integration/components/link-to/query-params-curly-test.js
index 6a61fd06ca4..f6903e4cf32 100644
--- a/packages/@ember/-internals/glimmer/tests/integration/components/link-to/query-params-curly-test.js
+++ b/packages/@ember/-internals/glimmer/tests/integration/components/link-to/query-params-curly-test.js
@@ -839,5 +839,45 @@ moduleFor(
});
});
}
+
+ ['@test the {{link-to}} component with dynamic segment and loading route should preserve query parameters'](
+ assert
+ ) {
+ this.router.map(function () {
+ this.route('foo', { path: ':foo' }, function () {
+ this.route('bar', function () {
+ this.route('baz');
+ });
+ });
+ });
+
+ this.addTemplate('foo.bar', `{{link-to 'Baz' 'foo.bar.baz' id='baz-link'}}`);
+
+ this.addTemplate('foo.bar.loading', 'Loading');
+
+ this.add(
+ 'controller:foo.bar',
+ Controller.extend({
+ queryParams: ['qux'],
+ qux: null,
+ })
+ );
+
+ this.add(
+ 'route:foo.bar.baz',
+ Route.extend({
+ model() {
+ return new RSVP.Promise((resolve) => {
+ setTimeout(resolve, 1);
+ });
+ },
+ })
+ );
+
+ return this.visit('/foo/bar/baz?qux=abc').then(() => {
+ let bazLink = this.$('#baz-link');
+ assert.equal(bazLink.attr('href'), '/foo/bar/baz?qux=abc');
+ });
+ }
}
);
diff --git a/packages/ember/tests/routing/query_params_test.js b/packages/ember/tests/routing/query_params_test.js
index b73a3ea4a72..b9c623cb746 100644
--- a/packages/ember/tests/routing/query_params_test.js
+++ b/packages/ember/tests/routing/query_params_test.js
@@ -1687,5 +1687,62 @@ moduleFor(
await runLoopSettled();
this.assertCurrentPath('/?foo=987');
}
+
+ async [`@test Updating single query parameter doesn't affect other query parameters. Issue #14438`](
+ assert
+ ) {
+ assert.expect(5);
+
+ this.router.map(function () {
+ this.route('grandparent', { path: 'grandparent/:foo' }, function () {
+ this.route('parent', function () {
+ this.route('child');
+ });
+ });
+ });
+
+ this.addTemplate('grandparent.parent.loading', 'Loading...');
+
+ this.add(
+ 'route:index',
+ Route.extend({
+ redirect() {
+ this.transitionTo('grandparent.parent.child', 1);
+ },
+ })
+ );
+
+ this.add(
+ 'route:grandparent.parent.child',
+ Route.extend({
+ model() {
+ return Promise.resolve();
+ },
+ })
+ );
+
+ this.add(
+ 'controller:grandparent.parent',
+ Controller.extend({
+ queryParams: ['foo', 'bar'],
+
+ foo: 'FOO',
+ bar: 'BAR',
+ })
+ );
+
+ await this.visit('/');
+
+ this.assertCurrentPath('/grandparent/1/parent/child');
+ let parentController = this.getController('grandparent.parent');
+
+ await this.setAndFlush(parentController, 'foo', 'NEW_FOO');
+ assert.equal(parentController.foo, 'NEW_FOO');
+ this.assertCurrentPath('/grandparent/1/parent/child?foo=NEW_FOO');
+
+ await this.setAndFlush(parentController, 'bar', 'NEW_BAR');
+ assert.equal(parentController.bar, 'NEW_BAR');
+ this.assertCurrentPath('/grandparent/1/parent/child?bar=NEW_BAR&foo=NEW_FOO');
+ }
}
);
diff --git a/yarn.lock b/yarn.lock
index ff6a531a37b..004ee0d0f06 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -8150,10 +8150,10 @@ route-recognizer@^0.3.4:
resolved "https://registry.yarnpkg.com/route-recognizer/-/route-recognizer-0.3.4.tgz#39ab1ffbce1c59e6d2bdca416f0932611e4f3ca3"
integrity sha512-2+MhsfPhvauN1O8KaXpXAOfR/fwe8dnUXVM+xw7yt40lJRfPVQxV6yryZm0cgRvAj5fMF/mdRZbL2ptwbs5i2g==
-router_js@^7.1.0:
- version "7.1.0"
- resolved "https://registry.yarnpkg.com/router_js/-/router_js-7.1.0.tgz#d2a47d7224a30f3b6416be20c9c80868fc14ff0c"
- integrity sha512-03n6mJCD6hTX4bUkowS+HcsyI9ghP3AxmtVSRnMmDWzykNlHE/wXy+hbybdHmnOH2sDe97L/4V7q6MfrVQBoIg==
+router_js@^7.1.1:
+ version "7.1.1"
+ resolved "https://registry.yarnpkg.com/router_js/-/router_js-7.1.1.tgz#cb7614a96cfb6bc65c066668b2dd32e3ad7ca38d"
+ integrity sha512-kOdKqBj7aj9GusG0umtWgkTtNtDspT9EfJNnJN9B8g0DDNp9CdIwpO+2Qnmf/fNos38Pj9jlfU44l/oycn5goQ==
dependencies:
"@glimmer/env" "^0.1.7"