Revert "fix(router): navigating to the current location works (#19463)"

This reverts commit b67d574a95.
This commit is contained in:
Chuck Jazdzewski 2017-10-06 18:15:19 -07:00
parent 0cc87c5ba1
commit 8e5b582b61
3 changed files with 95 additions and 120 deletions

View File

@ -41,9 +41,7 @@ export class SpyLocation implements Location {
return currPath == givenPath + (query.length > 0 ? ('?' + query) : ''); return currPath == givenPath + (query.length > 0 ? ('?' + query) : '');
} }
simulateUrlPop(pathname: string) { simulateUrlPop(pathname: string) { this._subject.emit({'url': pathname, 'pop': true}); }
this._subject.emit({'url': pathname, 'pop': true, 'type': 'popstate'});
}
simulateHashChange(pathname: string) { simulateHashChange(pathname: string) {
// Because we don't prevent the native event, the browser will independently update the path // Because we don't prevent the native event, the browser will independently update the path

View File

@ -43,12 +43,12 @@ declare let Zone: any;
*/ */
export interface NavigationExtras { export interface NavigationExtras {
/** /**
* Enables relative navigation from the current ActivatedRoute. * Enables relative navigation from the current ActivatedRoute.
* *
* Configuration: * Configuration:
* *
* ``` * ```
* [{ * [{
* path: 'parent', * path: 'parent',
* component: ParentComponent, * component: ParentComponent,
* children: [{ * children: [{
@ -59,92 +59,92 @@ export interface NavigationExtras {
* component: ChildComponent * component: ChildComponent
* }] * }]
* }] * }]
* ``` * ```
* *
* Navigate to list route from child route: * Navigate to list route from child route:
* *
* ``` * ```
* @Component({...}) * @Component({...})
* class ChildComponent { * class ChildComponent {
* constructor(private router: Router, private route: ActivatedRoute) {} * constructor(private router: Router, private route: ActivatedRoute) {}
* *
* go() { * go() {
* this.router.navigate(['../list'], { relativeTo: this.route }); * this.router.navigate(['../list'], { relativeTo: this.route });
* } * }
* } * }
* ``` * ```
*/ */
relativeTo?: ActivatedRoute|null; relativeTo?: ActivatedRoute|null;
/** /**
* Sets query parameters to the URL. * Sets query parameters to the URL.
* *
* ``` * ```
* // Navigate to /results?page=1 * // Navigate to /results?page=1
* this.router.navigate(['/results'], { queryParams: { page: 1 } }); * this.router.navigate(['/results'], { queryParams: { page: 1 } });
* ``` * ```
*/ */
queryParams?: Params|null; queryParams?: Params|null;
/** /**
* Sets the hash fragment for the URL. * Sets the hash fragment for the URL.
* *
* ``` * ```
* // Navigate to /results#top * // Navigate to /results#top
* this.router.navigate(['/results'], { fragment: 'top' }); * this.router.navigate(['/results'], { fragment: 'top' });
* ``` * ```
*/ */
fragment?: string; fragment?: string;
/** /**
* Preserves the query parameters for the next navigation. * Preserves the query parameters for the next navigation.
* *
* deprecated, use `queryParamsHandling` instead * deprecated, use `queryParamsHandling` instead
* *
* ``` * ```
* // Preserve query params from /results?page=1 to /view?page=1 * // Preserve query params from /results?page=1 to /view?page=1
* this.router.navigate(['/view'], { preserveQueryParams: true }); * this.router.navigate(['/view'], { preserveQueryParams: true });
* ``` * ```
* *
* @deprecated since v4 * @deprecated since v4
*/ */
preserveQueryParams?: boolean; preserveQueryParams?: boolean;
/** /**
* config strategy to handle the query parameters for the next navigation. * config strategy to handle the query parameters for the next navigation.
* *
* ``` * ```
* // from /results?page=1 to /view?page=1&page=2 * // from /results?page=1 to /view?page=1&page=2
* this.router.navigate(['/view'], { queryParams: { page: 2 }, queryParamsHandling: "merge" }); * this.router.navigate(['/view'], { queryParams: { page: 2 }, queryParamsHandling: "merge" });
* ``` * ```
*/ */
queryParamsHandling?: QueryParamsHandling|null; queryParamsHandling?: QueryParamsHandling|null;
/** /**
* Preserves the fragment for the next navigation * Preserves the fragment for the next navigation
* *
* ``` * ```
* // Preserve fragment from /results#top to /view#top * // Preserve fragment from /results#top to /view#top
* this.router.navigate(['/view'], { preserveFragment: true }); * this.router.navigate(['/view'], { preserveFragment: true });
* ``` * ```
*/ */
preserveFragment?: boolean; preserveFragment?: boolean;
/** /**
* Navigates without pushing a new state into history. * Navigates without pushing a new state into history.
* *
* ``` * ```
* // Navigate silently to /view * // Navigate silently to /view
* this.router.navigate(['/view'], { skipLocationChange: true }); * this.router.navigate(['/view'], { skipLocationChange: true });
* ``` * ```
*/ */
skipLocationChange?: boolean; skipLocationChange?: boolean;
/** /**
* Navigates while replacing the current state in history. * Navigates while replacing the current state in history.
* *
* ``` * ```
* // Navigate to /view * // Navigate to /view
* this.router.navigate(['/view'], { replaceUrl: true }); * this.router.navigate(['/view'], { replaceUrl: true });
* ``` * ```
*/ */
replaceUrl?: boolean; replaceUrl?: boolean;
} }
@ -518,18 +518,11 @@ export class Router {
// Because of a bug in IE and Edge, the location class fires two events (popstate and // Because of a bug in IE and Edge, the location class fires two events (popstate and
// hashchange) every single time. The second one should be ignored. Otherwise, the URL will // hashchange) every single time. The second one should be ignored. Otherwise, the URL will
// flicker. Handles the case when a popstate was emitted first. // flicker.
if (lastNavigation && source == 'hashchange' && lastNavigation.source === 'popstate' && if (lastNavigation && source == 'hashchange' && lastNavigation.source === 'popstate' &&
lastNavigation.rawUrl.toString() === rawUrl.toString()) { lastNavigation.rawUrl.toString() === rawUrl.toString()) {
return Promise.resolve(true); // return value is not used return Promise.resolve(true); // return value is not used
} }
// Because of a bug in IE and Edge, the location class fires two events (popstate and
// hashchange) every single time. The second one should be ignored. Otherwise, the URL will
// flicker. Handles the case when a hashchange was emitted first.
if (lastNavigation && source == 'popstate' && lastNavigation.source === 'hashchange' &&
lastNavigation.rawUrl.toString() === rawUrl.toString()) {
return Promise.resolve(true); // return value is not used
}
let resolve: any = null; let resolve: any = null;
let reject: any = null; let reject: any = null;
@ -552,7 +545,7 @@ export class Router {
const url = this.urlHandlingStrategy.extract(rawUrl); const url = this.urlHandlingStrategy.extract(rawUrl);
const urlTransition = !this.navigated || url.toString() !== this.currentUrlTree.toString(); const urlTransition = !this.navigated || url.toString() !== this.currentUrlTree.toString();
if (this.urlHandlingStrategy.shouldProcessUrl(rawUrl)) { if (urlTransition && this.urlHandlingStrategy.shouldProcessUrl(rawUrl)) {
(this.events as Subject<Event>).next(new NavigationStart(id, this.serializeUrl(url))); (this.events as Subject<Event>).next(new NavigationStart(id, this.serializeUrl(url)));
Promise.resolve() Promise.resolve()
.then( .then(

View File

@ -50,29 +50,6 @@ describe('Integration', () => {
expect(fixture.nativeElement).toHaveText('route'); expect(fixture.nativeElement).toHaveText('route');
}))); })));
it('should navigate to the current URL',
fakeAsync(inject([Router, Location], (router: Router) => {
router.resetConfig([
{path: '', component: SimpleCmp},
{path: 'simple', component: SimpleCmp},
]);
const fixture = createRoot(router, RootCmp);
const events: Event[] = [];
router.events.subscribe(e => onlyNavigationStartAndEnd(e) && events.push(e));
router.navigateByUrl('/simple');
tick();
router.navigateByUrl('/simple');
tick();
expectEvents(events, [
[NavigationStart, '/simple'], [NavigationEnd, '/simple'], [NavigationStart, '/simple'],
[NavigationEnd, '/simple']
]);
})));
describe('should execute navigations serially', () => { describe('should execute navigations serially', () => {
let log: any[] = []; let log: any[] = [];
@ -451,7 +428,7 @@ describe('Integration', () => {
}]); }]);
const recordedEvents: any[] = []; const recordedEvents: any[] = [];
router.events.forEach(e => onlyNavigationStartAndEnd(e) && recordedEvents.push(e)); router.events.forEach(e => e instanceof RouterEvent && recordedEvents.push(e));
router.navigateByUrl('/team/22/user/victor'); router.navigateByUrl('/team/22/user/victor');
advance(fixture); advance(fixture);
@ -465,8 +442,15 @@ describe('Integration', () => {
expect(fixture.nativeElement).toHaveText('team 22 [ user fedor, right: ]'); expect(fixture.nativeElement).toHaveText('team 22 [ user fedor, right: ]');
expectEvents(recordedEvents, [ expectEvents(recordedEvents, [
[NavigationStart, '/team/22/user/victor'], [NavigationEnd, '/team/22/user/victor'], [NavigationStart, '/team/22/user/victor'], [RoutesRecognized, '/team/22/user/victor'],
[NavigationStart, '/team/22/user/fedor'], [NavigationEnd, '/team/22/user/fedor'] [GuardsCheckStart, '/team/22/user/victor'], [GuardsCheckEnd, '/team/22/user/victor'],
[ResolveStart, '/team/22/user/victor'], [ResolveEnd, '/team/22/user/victor'],
[NavigationEnd, '/team/22/user/victor'],
[NavigationStart, '/team/22/user/fedor'], [RoutesRecognized, '/team/22/user/fedor'],
[GuardsCheckStart, '/team/22/user/fedor'], [GuardsCheckEnd, '/team/22/user/fedor'],
[ResolveStart, '/team/22/user/fedor'], [ResolveEnd, '/team/22/user/fedor'],
[NavigationEnd, '/team/22/user/fedor']
]); ]);
}))); })));
@ -3505,30 +3489,34 @@ describe('Integration', () => {
}]); }]);
const events: any[] = []; const events: any[] = [];
router.events.subscribe(e => onlyNavigationStartAndEnd(e) && events.push(e)); router.events.subscribe(e => e instanceof RouterEvent && events.push(e));
location.go('/include/user/kate(aux:excluded)'); location.go('/include/user/kate(aux:excluded)');
advance(fixture); advance(fixture);
expect(location.path()).toEqual('/include/user/kate(aux:excluded)'); expect(location.path()).toEqual('/include/user/kate(aux:excluded)');
expectEvents( expectEvents(events, [
events, [NavigationStart, '/include/user/kate'], [RoutesRecognized, '/include/user/kate'],
[[NavigationStart, '/include/user/kate'], [NavigationEnd, '/include/user/kate']]); [GuardsCheckStart, '/include/user/kate'], [GuardsCheckEnd, '/include/user/kate'],
[ResolveStart, '/include/user/kate'], [ResolveEnd, '/include/user/kate'],
[NavigationEnd, '/include/user/kate']
]);
events.splice(0); events.splice(0);
location.go('/include/user/kate(aux:excluded2)'); location.go('/include/user/kate(aux:excluded2)');
advance(fixture); advance(fixture);
expectEvents( expectEvents(events, []);
events,
[[NavigationStart, '/include/user/kate'], [NavigationEnd, '/include/user/kate']]);
events.splice(0);
router.navigateByUrl('/include/simple'); router.navigateByUrl('/include/simple');
advance(fixture); advance(fixture);
expect(location.path()).toEqual('/include/simple(aux:excluded2)'); expect(location.path()).toEqual('/include/simple(aux:excluded2)');
expectEvents( expectEvents(events, [
events, [[NavigationStart, '/include/simple'], [NavigationEnd, '/include/simple']]); [NavigationStart, '/include/simple'], [RoutesRecognized, '/include/simple'],
[GuardsCheckStart, '/include/simple'], [GuardsCheckEnd, '/include/simple'],
[ResolveStart, '/include/simple'], [ResolveEnd, '/include/simple'],
[NavigationEnd, '/include/simple']
]);
}))); })));
}); });
}); });
@ -3647,10 +3635,6 @@ function expectEvents(events: Event[], pairs: any[]) {
} }
} }
function onlyNavigationStartAndEnd(e: Event): boolean {
return e instanceof NavigationStart || e instanceof NavigationEnd;
}
@Component( @Component(
{selector: 'link-cmp', template: `<a routerLink="/team/33/simple" [target]="'_self'">link</a>`}) {selector: 'link-cmp', template: `<a routerLink="/team/33/simple" [target]="'_self'">link</a>`})
class StringLinkCmp { class StringLinkCmp {