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';
|
||||
|
||||
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 {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
dispose(): void { this.locationSubscription.unsubscribe(); }
|
||||
|
||||
private setUpLocationChangeListener(): void {
|
||||
this.locationSubscription = <any>this.location.subscribe((change) => {
|
||||
|
|
|
@ -153,20 +153,53 @@ describe("Integration", () => {
|
|||
|
||||
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({
|
||||
selector: 'simple-cmp',
|
||||
template: `simple`,
|
||||
directives: [ROUTER_DIRECTIVES]
|
||||
directives: ROUTER_DIRECTIVES
|
||||
})
|
||||
class SimpleCmp {}
|
||||
class SimpleCmp {
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'team-cmp',
|
||||
template: `team {{id | async}} { <router-outlet></router-outlet>, right: <router-outlet name="right"></router-outlet> }`,
|
||||
directives: [ROUTER_DIRECTIVES]
|
||||
directives: ROUTER_DIRECTIVES
|
||||
})
|
||||
class TeamCmp {
|
||||
id: Observable<string>;
|
||||
|
|
Loading…
Reference in New Issue