From e4d5a5f003be20ddc68bcbb0b0e9de4083375518 Mon Sep 17 00:00:00 2001 From: Andy Howell Date: Tue, 6 Sep 2016 12:39:53 +0100 Subject: [PATCH] fix(router): add support for query params with mulitple values closes #11373 --- modules/@angular/router/src/url_tree.ts | 29 ++++++++++++++++--- .../router/test/url_serializer.spec.ts | 5 ++++ 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/modules/@angular/router/src/url_tree.ts b/modules/@angular/router/src/url_tree.ts index af920342a5d46..bca907309cad5 100644 --- a/modules/@angular/router/src/url_tree.ts +++ b/modules/@angular/router/src/url_tree.ts @@ -370,9 +370,14 @@ function serializeParams(params: {[key: string]: string}): string { return pairs(params).map(p => `;${encode(p.first)}=${encode(p.second)}`).join(''); } -function serializeQueryParams(params: {[key: string]: string}): string { - const strs = pairs(params).map(p => `${encode(p.first)}=${encode(p.second)}`); - return strs.length > 0 ? `?${strs.join("&")}` : ''; +function serializeQueryParams(params: {[key: string]: any}): string { + const strParams: string[] = Object.keys(params).map((name) => { + const value = params[name]; + return Array.isArray(value) ? value.map(v => `${encode(name)}=${encode(v)}`).join('&') : + `${encode(name)}=${encode(value)}`; + }); + + return strParams.length ? `?${strParams.join("&")}` : ''; } class Pair { @@ -534,6 +539,7 @@ class UrlParser { params[decode(key)] = decode(value); } + // Parse a single query parameter `name[=value]` parseQueryParam(params: {[key: string]: any}): void { const key = matchQueryParams(this.remaining); if (!key) { @@ -549,7 +555,22 @@ class UrlParser { this.capture(value); } } - params[decode(key)] = decode(value); + + const decodedKey = decode(key); + const decodedVal = decode(value); + + if (params.hasOwnProperty(decodedKey)) { + // Append to existing values + let currentVal = params[decodedKey]; + if (!Array.isArray(currentVal)) { + currentVal = [currentVal]; + params[decodedKey] = currentVal; + } + currentVal.push(decodedVal); + } else { + // Create a new value + params[decodedKey] = decodedVal; + } } parseParens(allowPrimary: boolean): {[key: string]: UrlSegmentGroup} { diff --git a/modules/@angular/router/test/url_serializer.spec.ts b/modules/@angular/router/test/url_serializer.spec.ts index 3cfdc6de2b50f..abf426d91b4a3 100644 --- a/modules/@angular/router/test/url_serializer.spec.ts +++ b/modules/@angular/router/test/url_serializer.spec.ts @@ -160,6 +160,11 @@ describe('url serializer', () => { expect(url.serialize(tree)).toEqual('/one?a='); }); + it('should handle multiple query params of the same name into an array', () => { + const tree = url.parse('/one?a=foo&a=bar&a=swaz'); + expect(tree.queryParams).toEqual({a: ['foo', 'bar', 'swaz']}); + }); + it('should parse fragment', () => { const tree = url.parse('/one#two'); expect(tree.fragment).toEqual('two');