X Tutup
Skip to content

Commit 8bc40d3

Browse files
committed
fix(router): properly read and serialize query params
This splits out `path` and `query` into separate params for `location.go` and related methods so that we can handle them properly in both `PathLocationStrategy` and `HashLocationStrategy`. This handles the problem of not reading query params to populate `Location` on the initial page load. Closes #3957 Closes #4225 Closes #3784
1 parent 440fd11 commit 8bc40d3

File tree

9 files changed

+60
-27
lines changed

9 files changed

+60
-27
lines changed

modules/angular2/src/mock/location_mock.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ export class SpyLocation implements Location {
77
/** @internal */
88
_path: string = '';
99
/** @internal */
10+
_query: string = '';
11+
/** @internal */
1012
_subject: EventEmitter = new EventEmitter();
1113
/** @internal */
1214
_baseHref: string = '';
@@ -21,12 +23,15 @@ export class SpyLocation implements Location {
2123

2224
normalizeAbsolutely(url: string): string { return this._baseHref + url; }
2325

24-
go(url: string) {
25-
url = this.normalizeAbsolutely(url);
26-
if (this._path == url) {
26+
go(path: string, query: string = '') {
27+
path = this.normalizeAbsolutely(path);
28+
if (this._path == path && this._query == query) {
2729
return;
2830
}
29-
this._path = url;
31+
this._path = path;
32+
this._query = query;
33+
34+
var url = path + (query.length > 0 ? ('?' + query) : '');
3035
this.urlChanges.push(url);
3136
}
3237

modules/angular2/src/mock/mock_location_strategy.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@ export class MockLocationStrategy extends LocationStrategy {
2222
ObservableWrapper.callNext(this._subject, {'url': pathname});
2323
}
2424

25-
pushState(ctx: any, title: string, url: string): void {
25+
pushState(ctx: any, title: string, path: string, query: string): void {
2626
this.internalTitle = title;
27+
28+
var url = path + (query.length > 0 ? ('?' + query) : '');
2729
this.internalPath = url;
2830
this.urlChanges.push(url);
2931
}

modules/angular2/src/router/hash_location_strategy.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {DOM} from 'angular2/src/core/dom/dom_adapter';
22
import {Injectable} from 'angular2/angular2';
3-
import {LocationStrategy} from './location_strategy';
3+
import {LocationStrategy, normalizeQueryParams} from './location_strategy';
44
import {EventListener, History, Location} from 'angular2/src/core/facade/browser';
55

66
/**
@@ -61,11 +61,18 @@ export class HashLocationStrategy extends LocationStrategy {
6161
// Dart will complain if a call to substring is
6262
// executed with a position value that extends the
6363
// length of string.
64-
return path.length > 0 ? path.substring(1) : path;
64+
return (path.length > 0 ? path.substring(1) : path) +
65+
normalizeQueryParams(this._location.search);
6566
}
6667

67-
pushState(state: any, title: string, url: string) {
68-
this._history.pushState(state, title, '#' + url);
68+
pushState(state: any, title: string, path: string, queryParams: string) {
69+
var url = path + normalizeQueryParams(queryParams);
70+
if (url.length == 0) {
71+
url = this._location.pathname;
72+
} else {
73+
url = '#' + url;
74+
}
75+
this._history.pushState(state, title, url);
6976
}
7077

7178
forward(): void { this._history.forward(); }

modules/angular2/src/router/instruction.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,12 +94,18 @@ export class PrimaryInstruction {
9494
}
9595

9696
export function stringifyInstruction(instruction: Instruction): string {
97-
var params = instruction.component.urlParams.length > 0 ?
98-
('?' + instruction.component.urlParams.join('&')) :
99-
'';
97+
return stringifyInstructionPath(instruction) + stringifyInstructionQuery(instruction);
98+
}
10099

100+
export function stringifyInstructionPath(instruction: Instruction): string {
101101
return instruction.component.urlPath + stringifyAux(instruction) +
102-
stringifyPrimary(instruction.child) + params;
102+
stringifyPrimary(instruction.child);
103+
}
104+
105+
export function stringifyInstructionQuery(instruction: Instruction): string {
106+
return instruction.component.urlParams.length > 0 ?
107+
('?' + instruction.component.urlParams.join('&')) :
108+
'';
103109
}
104110

105111
function stringifyPrimary(instruction: Instruction): string {

modules/angular2/src/router/location.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,9 +125,9 @@ export class Location {
125125
* Changes the browsers URL to the normalized version of the given URL, and pushes a
126126
* new item onto the platform's history.
127127
*/
128-
go(url: string): void {
129-
var finalUrl = this.normalizeAbsolutely(url);
130-
this.platformStrategy.pushState(null, '', finalUrl);
128+
go(path: string, query: string = ''): void {
129+
var absolutePath = this.normalizeAbsolutely(path);
130+
this.platformStrategy.pushState(null, '', absolutePath, query);
131131
}
132132

133133
/**

modules/angular2/src/router/location_strategy.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,13 @@
1616
*/
1717
export abstract class LocationStrategy {
1818
abstract path(): string;
19-
abstract pushState(ctx: any, title: string, url: string): void;
19+
abstract pushState(state: any, title: string, url: string, queryParams: string): void;
2020
abstract forward(): void;
2121
abstract back(): void;
2222
abstract onPopState(fn: (_: any) => any): void;
2323
abstract getBaseHref(): string;
2424
}
25+
26+
export function normalizeQueryParams(params: string): string {
27+
return (params.length > 0 && params.substring(0, 1) != '?') ? ('?' + params) : params;
28+
}

modules/angular2/src/router/path_location_strategy.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import {DOM} from 'angular2/src/core/dom/dom_adapter';
22
import {Injectable} from 'angular2/angular2';
33
import {EventListener, History, Location} from 'angular2/src/core/facade/browser';
4-
import {LocationStrategy} from './location_strategy';
4+
import {LocationStrategy, normalizeQueryParams} from './location_strategy';
55

66
/**
77
* `PathLocationStrategy` is a {@link LocationStrategy} used to configure the
@@ -67,9 +67,11 @@ export class PathLocationStrategy extends LocationStrategy {
6767

6868
getBaseHref(): string { return this._baseHref; }
6969

70-
path(): string { return this._location.pathname; }
70+
path(): string { return this._location.pathname + normalizeQueryParams(this._location.search); }
7171

72-
pushState(state: any, title: string, url: string) { this._history.pushState(state, title, url); }
72+
pushState(state: any, title: string, url: string, queryParams: string) {
73+
this._history.pushState(state, title, (url + normalizeQueryParams(queryParams)));
74+
}
7375

7476
forward(): void { this._history.forward(); }
7577

modules/angular2/src/router/router.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,13 @@ import {
1515
} from 'angular2/src/core/facade/lang';
1616
import {BaseException, WrappedException} from 'angular2/src/core/facade/exceptions';
1717
import {RouteRegistry} from './route_registry';
18-
import {ComponentInstruction, Instruction, stringifyInstruction} from './instruction';
18+
import {
19+
ComponentInstruction,
20+
Instruction,
21+
stringifyInstruction,
22+
stringifyInstructionPath,
23+
stringifyInstructionQuery
24+
} from './instruction';
1925
import {RouterOutlet} from './router_outlet';
2026
import {Location} from './location';
2127
import {getCanActivateHook} from './route_lifecycle_reflector';
@@ -472,13 +478,14 @@ export class RootRouter extends Router {
472478
}
473479

474480
commit(instruction: Instruction, _skipLocationChange: boolean = false): Promise<any> {
475-
var emitUrl = stringifyInstruction(instruction);
476-
if (emitUrl.length > 0) {
477-
emitUrl = '/' + emitUrl;
481+
var emitPath = stringifyInstructionPath(instruction);
482+
var emitQuery = stringifyInstructionQuery(instruction);
483+
if (emitPath.length > 0) {
484+
emitPath = '/' + emitPath;
478485
}
479486
var promise = super.commit(instruction);
480487
if (!_skipLocationChange) {
481-
promise = promise.then((_) => { this._location.go(emitUrl); });
488+
promise = promise.then((_) => { this._location.go(emitPath, emitQuery); });
482489
}
483490
return promise;
484491
}

modules/angular2/src/router/url_parser.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,10 @@ export function pathSegmentsToUrl(pathSegments: string[]): Url {
7070
return url;
7171
}
7272

73-
var SEGMENT_RE = RegExpWrapper.create('^[^\\/\\(\\)\\?;=&]+');
73+
var SEGMENT_RE = RegExpWrapper.create('^[^\\/\\(\\)\\?;=&#]+');
7474
function matchUrlSegment(str: string): string {
7575
var match = RegExpWrapper.firstMatch(SEGMENT_RE, str);
76-
return isPresent(match) ? match[0] : null;
76+
return isPresent(match) ? match[0] : '';
7777
}
7878

7979
export class UrlParser {

0 commit comments

Comments
 (0)
X Tutup