feat: add RouterLink
This commit is contained in:
parent
c9b4bcf689
commit
5b371736b2
|
@ -4,4 +4,6 @@ export { RouterState, ActivatedRoute } from './src/router_state';
|
||||||
export { RouterOutletMap } from './src/router_outlet_map';
|
export { RouterOutletMap } from './src/router_outlet_map';
|
||||||
|
|
||||||
import { RouterOutlet } from './src/directives/router_outlet';
|
import { RouterOutlet } from './src/directives/router_outlet';
|
||||||
export const ROUTER_DIRECTIVES = [RouterOutlet];
|
import { RouterLink } from './src/directives/router_link';
|
||||||
|
|
||||||
|
export const ROUTER_DIRECTIVES = [RouterOutlet, RouterLink];
|
|
@ -0,0 +1,73 @@
|
||||||
|
import {
|
||||||
|
Directive,
|
||||||
|
HostListener,
|
||||||
|
HostBinding,
|
||||||
|
Input
|
||||||
|
} from '@angular/core';
|
||||||
|
import {Router} from '../router';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The RouterLink directive lets you link to specific parts of your app.
|
||||||
|
*
|
||||||
|
* Consider the following route configuration:
|
||||||
|
|
||||||
|
* ```
|
||||||
|
* [{ name: 'user', path: '/user', component: UserCmp }]
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* When linking to this `User` route, you can write:
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* <a [routerLink]="['/user']">link to user component</a>
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* RouterLink expects the value to be an array of path segments, followed by the params
|
||||||
|
* for that level of routing. For instance `['/team', {teamId: 1}, 'user', {userId: 2}]`
|
||||||
|
* means that we want to generate a link to `/team;teamId=1/user;userId=2`.
|
||||||
|
*
|
||||||
|
* The first segment name can be prepended with `/`, `./`, or `../`.
|
||||||
|
* If the segment begins with `/`, the router will look up the route from the root of the app.
|
||||||
|
* If the segment begins with `./`, or doesn't begin with a slash, the router will
|
||||||
|
* instead look in the current component's children for the route.
|
||||||
|
* And if the segment begins with `../`, the router will go up one level.
|
||||||
|
*/
|
||||||
|
@Directive({selector: '[routerLink]'})
|
||||||
|
export class RouterLink {
|
||||||
|
@Input() target: string;
|
||||||
|
private commands: any[]|null = null;
|
||||||
|
private absoluteUrl: string|null = null;
|
||||||
|
|
||||||
|
// the url displayed on the anchor element.
|
||||||
|
@HostBinding() href: string;
|
||||||
|
|
||||||
|
constructor(private router: Router) {}
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
set routerLink(data: any[] | string) {
|
||||||
|
if (Array.isArray(data)) {
|
||||||
|
this.commands = data;
|
||||||
|
this.absoluteUrl = null;
|
||||||
|
} else {
|
||||||
|
this.commands = null;
|
||||||
|
this.absoluteUrl = data;
|
||||||
|
}
|
||||||
|
this.updateTargetUrlAndHref();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@HostListener("click")
|
||||||
|
onClick(): boolean {
|
||||||
|
// If no target, or if target is _self, prevent default browser behavior
|
||||||
|
if (!(typeof this.target === "string") || this.target == '_self') {
|
||||||
|
this.router.navigateByUrl(this.absoluteUrl);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private updateTargetUrlAndHref(): void {
|
||||||
|
if (this.absoluteUrl) {
|
||||||
|
this.href = this.absoluteUrl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -66,6 +66,11 @@ export class Router {
|
||||||
resetConfig(config: RouterConfig): void {
|
resetConfig(config: RouterConfig): void {
|
||||||
this.config = config;
|
this.config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
dispose(): void { this.locationSubscription.unsubscribe(); }
|
||||||
|
|
||||||
private setUpLocationChangeListener(): void {
|
private setUpLocationChangeListener(): void {
|
||||||
this.locationSubscription = <any>this.location.subscribe((change) => {
|
this.locationSubscription = <any>this.location.subscribe((change) => {
|
||||||
|
|
|
@ -153,20 +153,53 @@ describe("Integration", () => {
|
||||||
|
|
||||||
expect(fixture.debugElement.nativeElement).toHaveText('');
|
expect(fixture.debugElement.nativeElement).toHaveText('');
|
||||||
})));
|
})));
|
||||||
|
|
||||||
|
describe("router links", () => {
|
||||||
|
it("should support string router links",
|
||||||
|
fakeAsync(inject([Router, TestComponentBuilder], (router, tcb) => {
|
||||||
|
router.resetConfig([
|
||||||
|
{ name: 'team', path: 'team/:id', component: TeamCmp, children: [
|
||||||
|
{ name: 'link', path: 'link', component: StringLinkCmp },
|
||||||
|
{ name: 'simple', path: 'simple', component: SimpleCmp }
|
||||||
|
] }
|
||||||
|
]);
|
||||||
|
|
||||||
|
const fixture = tcb.createFakeAsync(RootCmp);
|
||||||
|
advance(fixture);
|
||||||
|
|
||||||
|
router.navigateByUrl('/team/22/link');
|
||||||
|
advance(fixture);
|
||||||
|
expect(fixture.debugElement.nativeElement).toHaveText('team 22 { link, right: }');
|
||||||
|
|
||||||
|
const native = fixture.debugElement.nativeElement.querySelector("a");
|
||||||
|
expect(native.getAttribute("href")).toEqual("/team/33/simple");
|
||||||
|
native.click();
|
||||||
|
advance(fixture);
|
||||||
|
|
||||||
|
expect(fixture.debugElement.nativeElement).toHaveText('team 33 { simple, right: }');
|
||||||
|
})));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'link-cmp',
|
||||||
|
template: `<a routerLink="/team/33/simple">link</a>`,
|
||||||
|
directives: ROUTER_DIRECTIVES
|
||||||
|
})
|
||||||
|
class StringLinkCmp {}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'simple-cmp',
|
selector: 'simple-cmp',
|
||||||
template: `simple`,
|
template: `simple`,
|
||||||
directives: [ROUTER_DIRECTIVES]
|
directives: ROUTER_DIRECTIVES
|
||||||
})
|
})
|
||||||
class SimpleCmp {}
|
class SimpleCmp {
|
||||||
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'team-cmp',
|
selector: 'team-cmp',
|
||||||
template: `team {{id | async}} { <router-outlet></router-outlet>, right: <router-outlet name="right"></router-outlet> }`,
|
template: `team {{id | async}} { <router-outlet></router-outlet>, right: <router-outlet name="right"></router-outlet> }`,
|
||||||
directives: [ROUTER_DIRECTIVES]
|
directives: ROUTER_DIRECTIVES
|
||||||
})
|
})
|
||||||
class TeamCmp {
|
class TeamCmp {
|
||||||
id: Observable<string>;
|
id: Observable<string>;
|
||||||
|
|
Loading…
Reference in New Issue