diff --git a/modules/@angular/router/src/directives/router_link_active.ts b/modules/@angular/router/src/directives/router_link_active.ts index a66a6142d2..8f782f8f0b 100644 --- a/modules/@angular/router/src/directives/router_link_active.ts +++ b/modules/@angular/router/src/directives/router_link_active.ts @@ -52,6 +52,14 @@ import {RouterLink, RouterLinkWithHref} from './router_link'; * true}">Bob * ``` * + * You can assign the RouterLinkActive instance to a template variable and directly check + * the `isActive` status. + * ``` + * + * Bob {{ rla.isActive ? '(already open)' : ''}} + * + * ``` + * * Finally, you can apply the RouterLinkActive directive to an ancestor of a RouterLink. * * ``` @@ -69,8 +77,12 @@ import {RouterLink, RouterLinkWithHref} from './router_link'; * * @stable */ -@Directive({selector: '[routerLinkActive]'}) -export class RouterLinkActive implements OnChanges, OnDestroy, AfterContentInit { +@Directive({ + selector: '[routerLinkActive]', + exportAs: 'routerLinkActive', +}) +export class RouterLinkActive implements OnChanges, + OnDestroy, AfterContentInit { @ContentChildren(RouterLink, {descendants: true}) links: QueryList; @ContentChildren(RouterLinkWithHref, {descendants: true}) linksWithHrefs: QueryList; @@ -88,6 +100,8 @@ export class RouterLinkActive implements OnChanges, OnDestroy, AfterContentInit }); } + get isActive(): boolean { return this.hasActiveLink(); } + ngAfterContentInit(): void { this.links.changes.subscribe(s => this.update()); this.linksWithHrefs.changes.subscribe(s => this.update()); @@ -110,8 +124,11 @@ export class RouterLinkActive implements OnChanges, OnDestroy, AfterContentInit if (!this.links || !this.linksWithHrefs || !this.router.navigated) return; const isActive = this.hasActiveLink(); - this.classes.forEach( - c => this.renderer.setElementClass(this.element.nativeElement, c, isActive)); + this.classes.forEach(c => { + if (c) { + this.renderer.setElementClass(this.element.nativeElement, c, isActive); + } + }); } private isLinkActive(router: Router): (link: (RouterLink|RouterLinkWithHref)) => boolean { diff --git a/modules/@angular/router/test/integration.spec.ts b/modules/@angular/router/test/integration.spec.ts index 158dff2dec..f8bd35b264 100644 --- a/modules/@angular/router/test/integration.spec.ts +++ b/modules/@angular/router/test/integration.spec.ts @@ -1638,6 +1638,43 @@ describe('Integration', () => { expect(native.className).toEqual('active'); }))); + + it('should expose an isActive property', fakeAsync(() => { + @Component({ + template: ` +

{{rla.isActive}}

+ ` + }) + class ComponentWithRouterLink { + } + + TestBed.configureTestingModule({declarations: [ComponentWithRouterLink]}); + const router: Router = TestBed.get(Router); + + router.resetConfig([ + { + path: 'team', + component: TeamCmp, + }, + { + path: 'otherteam', + component: TeamCmp, + } + ]); + + const f = TestBed.createComponent(ComponentWithRouterLink); + router.navigateByUrl('/team'); + advance(f); + + const paragraph = f.nativeElement.querySelector('p'); + expect(paragraph.textContent).toEqual('true'); + + router.navigateByUrl('/otherteam'); + advance(f); + + expect(paragraph.textContent).toEqual('false'); + })); + }); describe('lazy loading', () => { @@ -2338,4 +2375,4 @@ function createRoot(router: Router, type: any): ComponentFixture { ] }) class TestModule { -} \ No newline at end of file +} diff --git a/tools/public_api_guard/router/index.d.ts b/tools/public_api_guard/router/index.d.ts index 109bc39f7a..6da66d6bae 100644 --- a/tools/public_api_guard/router/index.d.ts +++ b/tools/public_api_guard/router/index.d.ts @@ -233,6 +233,7 @@ export declare class RouterLink { /** @stable */ export declare class RouterLinkActive implements OnChanges, OnDestroy, AfterContentInit { + isActive: boolean; links: QueryList; linksWithHrefs: QueryList; routerLinkActive: string[] | string;