diff --git a/packages/router/src/directives/router_link_active.ts b/packages/router/src/directives/router_link_active.ts index 07c6e09217..5d548cabbc 100644 --- a/packages/router/src/directives/router_link_active.ts +++ b/packages/router/src/directives/router_link_active.ts @@ -118,21 +118,19 @@ export class RouterLinkActive implements OnChanges, private update(): void { if (!this.links || !this.linksWithHrefs || !this.router.navigated) return; - const hasActiveLinks = this.hasActiveLinks(); - - // react only when status has changed to prevent unnecessary dom updates - if (this.isActive !== hasActiveLinks) { - this.classes.forEach((c) => { - if (hasActiveLinks) { - this.renderer.addClass(this.element.nativeElement, c); - } else { - this.renderer.removeClass(this.element.nativeElement, c); - } - }); - Promise.resolve(hasActiveLinks).then(active => (this as{ - isActive: boolean - }).isActive = active); - } + Promise.resolve().then(() => { + const hasActiveLinks = this.hasActiveLinks(); + if (this.isActive !== hasActiveLinks) { + (this as any).isActive = hasActiveLinks; + this.classes.forEach((c) => { + if (hasActiveLinks) { + this.renderer.addClass(this.element.nativeElement, c); + } else { + this.renderer.removeClass(this.element.nativeElement, c); + } + }); + } + }); } private isLinkActive(router: Router): (link: (RouterLink|RouterLinkWithHref)) => boolean { diff --git a/packages/router/test/integration.spec.ts b/packages/router/test/integration.spec.ts index 5c78c3e083..722f0ad133 100644 --- a/packages/router/test/integration.spec.ts +++ b/packages/router/test/integration.spec.ts @@ -2655,6 +2655,7 @@ describe('Integration', () => { router.navigateByUrl('/team/22/link;exact=true'); advance(fixture); + advance(fixture); expect(location.path()).toEqual('/team/22/link;exact=true'); const nativeLink = fixture.nativeElement.querySelector('a'); @@ -2711,6 +2712,7 @@ describe('Integration', () => { router.navigateByUrl('/team/22/link;exact=true'); advance(fixture); + advance(fixture); expect(location.path()).toEqual('/team/22/link;exact=true'); const native = fixture.nativeElement.querySelector('#link-parent'); @@ -2739,6 +2741,7 @@ describe('Integration', () => { router.navigateByUrl('/team/22/link'); advance(fixture); + advance(fixture); expect(location.path()).toEqual('/team/22/link'); const native = fixture.nativeElement.querySelector('a'); diff --git a/packages/router/test/regression_integration.spec.ts b/packages/router/test/regression_integration.spec.ts index ddfcd2af38..d59c2c36d2 100644 --- a/packages/router/test/regression_integration.spec.ts +++ b/packages/router/test/regression_integration.spec.ts @@ -7,8 +7,9 @@ */ import {CommonModule} from '@angular/common'; -import {Component, NgModule, Type} from '@angular/core'; +import {Component, ContentChild, NgModule, TemplateRef, Type, ViewChild, ViewContainerRef} from '@angular/core'; import {ComponentFixture, TestBed, fakeAsync, tick} from '@angular/core/testing'; +import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter'; import {Router} from '@angular/router'; import {RouterTestingModule} from '@angular/router/testing'; @@ -56,6 +57,56 @@ describe('Integration', () => { instance.show = true; expect(() => advance(fixture)).not.toThrow(); })); + + it('should set isActive right after looking at its children -- #18983', fakeAsync(() => { + @Component({ + template: ` +