feat(router): update RouterLink to support query params and fragment
This commit is contained in:
parent
b0e7c14545
commit
33b518ad21
@ -2,7 +2,8 @@ import {
|
|||||||
Directive,
|
Directive,
|
||||||
HostListener,
|
HostListener,
|
||||||
HostBinding,
|
HostBinding,
|
||||||
Input
|
Input,
|
||||||
|
OnChanges
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import {Router} from '../router';
|
import {Router} from '../router';
|
||||||
import {ActivatedRoute} from '../router_state';
|
import {ActivatedRoute} from '../router_state';
|
||||||
@ -33,9 +34,11 @@ import {ActivatedRoute} from '../router_state';
|
|||||||
* And if the segment begins with `../`, the router will go up one level.
|
* And if the segment begins with `../`, the router will go up one level.
|
||||||
*/
|
*/
|
||||||
@Directive({selector: '[routerLink]'})
|
@Directive({selector: '[routerLink]'})
|
||||||
export class RouterLink {
|
export class RouterLink implements OnChanges {
|
||||||
@Input() target: string;
|
@Input() target: string;
|
||||||
private commands: any[] = [];
|
private commands: any[] = [];
|
||||||
|
@Input() queryParams: {[k:string]:any};
|
||||||
|
@Input() fragment: string;
|
||||||
|
|
||||||
// the url displayed on the anchor element.
|
// the url displayed on the anchor element.
|
||||||
@HostBinding() href: string;
|
@HostBinding() href: string;
|
||||||
@ -48,25 +51,36 @@ export class RouterLink {
|
|||||||
@Input()
|
@Input()
|
||||||
set routerLink(data: any[] | string) {
|
set routerLink(data: any[] | string) {
|
||||||
if (Array.isArray(data)) {
|
if (Array.isArray(data)) {
|
||||||
this.commands = data;
|
this.commands = <any>data;
|
||||||
} else {
|
} else {
|
||||||
this.commands = [data];
|
this.commands = [data];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnChanges(changes:{}):any {
|
||||||
this.updateTargetUrlAndHref();
|
this.updateTargetUrlAndHref();
|
||||||
}
|
}
|
||||||
|
|
||||||
@HostListener("click")
|
@HostListener("click")
|
||||||
onClick(): boolean {
|
onClick(): boolean {
|
||||||
// If no target, or if target is _self, prevent default browser behavior
|
// If no target, or if target is _self, prevent default browser behavior
|
||||||
if (!(typeof this.target === "string") || this.target == '_self') {
|
if (!(typeof this.target === "string") || this.target == '_self') {
|
||||||
this.router.navigate(this.commands, {relativeTo: this.route});
|
this.router.navigate(this.commands, {
|
||||||
|
relativeTo: this.route,
|
||||||
|
queryParameters: this.queryParams,
|
||||||
|
fragment: this.fragment
|
||||||
|
});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateTargetUrlAndHref(): void {
|
private updateTargetUrlAndHref(): void {
|
||||||
const tree = this.router.createUrlTree(this.commands, {relativeTo: this.route});
|
const tree = this.router.createUrlTree(this.commands, {
|
||||||
|
relativeTo: this.route,
|
||||||
|
queryParameters: this.queryParams,
|
||||||
|
fragment: this.fragment
|
||||||
|
});
|
||||||
if (tree) {
|
if (tree) {
|
||||||
this.href = this.router.serializeUrl(tree);
|
this.href = this.router.serializeUrl(tree);
|
||||||
}
|
}
|
||||||
|
@ -193,7 +193,7 @@ export class Router {
|
|||||||
navigate(commands: any[], extras: NavigationExtras = {}): Promise<boolean> {
|
navigate(commands: any[], extras: NavigationExtras = {}): Promise<boolean> {
|
||||||
return this.scheduleNavigation(this.createUrlTree(commands, extras), false);
|
return this.scheduleNavigation(this.createUrlTree(commands, extras), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serializes a {@link UrlTree} into a string.
|
* Serializes a {@link UrlTree} into a string.
|
||||||
*/
|
*/
|
||||||
|
@ -36,8 +36,11 @@ describe("Integration", () => {
|
|||||||
{provide: Location, useClass: SpyLocation},
|
{provide: Location, useClass: SpyLocation},
|
||||||
{
|
{
|
||||||
provide: Router,
|
provide: Router,
|
||||||
useFactory: (resolver, urlSerializer, outletMap, location, injector) =>
|
useFactory: (resolver, urlSerializer, outletMap, location, injector) => {
|
||||||
new Router(RootCmp, resolver, urlSerializer, outletMap, location, injector, config),
|
const r = new Router(RootCmp, resolver, urlSerializer, outletMap, location, injector, config);
|
||||||
|
r.initialNavigation();
|
||||||
|
return r;
|
||||||
|
},
|
||||||
deps: [ComponentResolver, UrlSerializer, RouterOutletMap, Location, Injector]
|
deps: [ComponentResolver, UrlSerializer, RouterOutletMap, Location, Injector]
|
||||||
},
|
},
|
||||||
{provide: ActivatedRoute, useFactory: (r) => r.routerState.root, deps: [Router]},
|
{provide: ActivatedRoute, useFactory: (r) => r.routerState.root, deps: [Router]},
|
||||||
@ -389,6 +392,32 @@ describe("Integration", () => {
|
|||||||
advance(fixture);
|
advance(fixture);
|
||||||
expect(fixture.debugElement.nativeElement).toHaveText('link');
|
expect(fixture.debugElement.nativeElement).toHaveText('link');
|
||||||
})));
|
})));
|
||||||
|
|
||||||
|
it("should support query params and fragments",
|
||||||
|
fakeAsync(inject([Router, Location, TestComponentBuilder], (router, location, tcb) => {
|
||||||
|
router.resetConfig([
|
||||||
|
{ path: 'team/:id', component: TeamCmp, children: [
|
||||||
|
{ path: 'link', component: LinkWithQueryParamsAndFragment },
|
||||||
|
{ path: 'simple', component: SimpleCmp }
|
||||||
|
] }
|
||||||
|
]);
|
||||||
|
|
||||||
|
const fixture = tcb.createFakeAsync(RootCmp);
|
||||||
|
advance(fixture);
|
||||||
|
|
||||||
|
router.navigateByUrl('/team/22/link');
|
||||||
|
advance(fixture);
|
||||||
|
|
||||||
|
const native = fixture.debugElement.nativeElement.querySelector("a");
|
||||||
|
expect(native.getAttribute("href")).toEqual("/team/22/simple?q=1#f");
|
||||||
|
native.click();
|
||||||
|
advance(fixture);
|
||||||
|
|
||||||
|
expect(fixture.debugElement.nativeElement)
|
||||||
|
.toHaveText('team 22 { simple, right: }');
|
||||||
|
|
||||||
|
expect(location.path()).toEqual('/team/22/simple?q=1#f');
|
||||||
|
})));
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("guards", () => {
|
describe("guards", () => {
|
||||||
@ -603,6 +632,13 @@ class AbsoluteLinkCmp {}
|
|||||||
})
|
})
|
||||||
class RelativeLinkCmp {}
|
class RelativeLinkCmp {}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'link-cmp',
|
||||||
|
template: `<a [routerLink]="['../simple']" [queryParams]="{q: '1'}" fragment="f">link</a>`,
|
||||||
|
directives: ROUTER_DIRECTIVES
|
||||||
|
})
|
||||||
|
class LinkWithQueryParamsAndFragment {}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'simple-cmp',
|
selector: 'simple-cmp',
|
||||||
template: `simple`,
|
template: `simple`,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user