fix(router): router link active should take all descendants into account

This commit is contained in:
vsavkin 2016-07-22 16:42:05 -07:00
parent 93a4ca652a
commit 8d90a5a4cf
2 changed files with 41 additions and 37 deletions

View File

@ -59,8 +59,9 @@ import {RouterLink, RouterLinkWithHref} from './router_link';
*/ */
@Directive({selector: '[routerLinkActive]'}) @Directive({selector: '[routerLinkActive]'})
export class RouterLinkActive implements OnChanges, OnDestroy, AfterContentInit { export class RouterLinkActive implements OnChanges, OnDestroy, AfterContentInit {
@ContentChildren(RouterLink) links: QueryList<RouterLink>; @ContentChildren(RouterLink, {descendants: true}) links: QueryList<RouterLink>;
@ContentChildren(RouterLinkWithHref) linksWithHrefs: QueryList<RouterLinkWithHref>; @ContentChildren(RouterLinkWithHref, {descendants: true})
linksWithHrefs: QueryList<RouterLinkWithHref>;
private classes: string[] = []; private classes: string[] = [];
private subscription: Subscription; private subscription: Subscription;

View File

@ -1226,34 +1226,35 @@ describe('Integration', () => {
it('should set the class on a parent element when the link is active', it('should set the class on a parent element when the link is active',
fakeAsync(inject( fakeAsync(inject(
[Router, TestComponentBuilder, Location], [Router, TestComponentBuilder, Location],
(router: Router, tcb: TestComponentBuilder, location: Location) => { (router: Router, tcb: TestComponentBuilder, location: Location) => {
const fixture = createRoot(tcb, router, RootCmp); const fixture = createRoot(tcb, router, RootCmp);
router.resetConfig([{ router.resetConfig([{
path: 'team/:id', path: 'team/:id',
component: TeamCmp, component: TeamCmp,
children: [{ children: [{
path: 'link', path: 'link',
component: DummyLinkWithParentCmp, component: DummyLinkWithParentCmp,
children: children: [
[{path: 'simple', component: SimpleCmp}, {path: '', component: BlankCmp}] {path: 'simple', component: SimpleCmp}, {path: '', component: BlankCmp}
}] ]
}]); }]
}]);
router.navigateByUrl('/team/22/link;exact=true'); router.navigateByUrl('/team/22/link;exact=true');
advance(fixture); advance(fixture);
expect(location.path()).toEqual('/team/22/link;exact=true'); expect(location.path()).toEqual('/team/22/link;exact=true');
const native = fixture.debugElement.nativeElement.querySelector('link-parent'); const native = fixture.debugElement.nativeElement.querySelector('link-parent');
expect(native.className).toEqual('active'); expect(native.className).toEqual('active');
router.navigateByUrl('/team/22/link/simple'); router.navigateByUrl('/team/22/link/simple');
advance(fixture); advance(fixture);
expect(location.path()).toEqual('/team/22/link/simple'); expect(location.path()).toEqual('/team/22/link/simple');
expect(native.className).toEqual(''); expect(native.className).toEqual('');
}))); })));
it('should set the class when the link is active', it('should set the class when the link is active',
fakeAsync(inject( fakeAsync(inject(
@ -1439,17 +1440,6 @@ class DummyLinkCmp {
constructor(route: ActivatedRoute) { this.exact = (<any>route.snapshot.params).exact === 'true'; } constructor(route: ActivatedRoute) { this.exact = (<any>route.snapshot.params).exact === 'true'; }
} }
@Component({
selector: 'link-cmp',
template:
`<router-outlet></router-outlet><link-parent routerLinkActive="active" [routerLinkActiveOptions]="{exact: exact}"><a [routerLink]="['./']">link</a></link-parent>`,
directives: ROUTER_DIRECTIVES
})
class DummyLinkWithParentCmp {
private exact: boolean;
constructor(route: ActivatedRoute) { this.exact = (<any>route.snapshot.params).exact === 'true'; }
}
@Component({ @Component({
selector: 'link-cmp', selector: 'link-cmp',
template: `<a [routerLink]="['../simple']">link</a>`, template: `<a [routerLink]="['../simple']">link</a>`,
@ -1566,6 +1556,19 @@ class LinkInNgIf {
alwaysTrue = true; alwaysTrue = true;
} }
@Component({
selector: 'link-cmp',
template: `<router-outlet></router-outlet>
<link-parent routerLinkActive="active" [routerLinkActiveOptions]="{exact: exact}">
<div ngClass="{one: 'true'}"><a [routerLink]="['./']">link</a></div>
</link-parent>`,
directives: ROUTER_DIRECTIVES
})
class DummyLinkWithParentCmp {
private exact: boolean;
constructor(route: ActivatedRoute) { this.exact = (<any>route.snapshot.params).exact === 'true'; }
}
@Component({ @Component({
selector: 'root-cmp', selector: 'root-cmp',
template: `<router-outlet></router-outlet>`, template: `<router-outlet></router-outlet>`,