Skip to content

Commit

Permalink
fix(uiSrefActive): Fix nested UISrefActive where UISref components ar…
Browse files Browse the repository at this point in the history
…e added/removed dynamically (#811)

Fixes #760
  • Loading branch information
christopherthielen committed Jul 3, 2020
1 parent 36632f2 commit 8d35dc1
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 7 deletions.
4 changes: 3 additions & 1 deletion src/directives/uiSrefStatus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,9 @@ export class UISrefStatus {

// Watch the @ContentChildren UISref[] components and get their target states
this._srefs$ = new BehaviorSubject(withHostSref(this._srefs.toArray()));
this._srefChangesSub = this._srefs.changes.subscribe((srefs) => this._srefs$.next(withHostSref(srefs)));
this._srefChangesSub = this._srefs.changes.subscribe((srefs: QueryList<UISref>) =>
this._srefs$.next(withHostSref(srefs.toArray()))
);

const targetStates$: Observable<TargetState[]> = this._srefs$.pipe(
switchMap((srefs: UISref[]) => combineLatest<TargetState[]>(srefs.map((sref) => sref.targetState$)))
Expand Down
71 changes: 65 additions & 6 deletions test/uiSrefActive/uiSrefActive.spec.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import { Component } from '@angular/core';
import { Component, Type } from '@angular/core';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';

import { UIRouter } from '@uirouter/core';
import { UIRouterModule } from '../../src/uiRouterNgModule';
import { UISrefActive } from '../../src';
import { UIRouterModule } from '../../src/uiRouterNgModule';

describe('uiSrefActive', () => {
const tick = () => new Promise(resolve => setTimeout(resolve));
const tick = () => new Promise((resolve) => setTimeout(resolve));

const initialize = (Component, states) => {
const initialize = <T>(ComponentClass: Type<T>, states) => {
const fixture = TestBed.configureTestingModule({
declarations: [Component],
declarations: [ComponentClass],
imports: [UIRouterModule.forRoot({ useHash: true, states })],
}).createComponent(Component);
}).createComponent(ComponentClass);
fixture.detectChanges();

return fixture;
Expand Down Expand Up @@ -65,4 +65,63 @@ describe('uiSrefActive', () => {
});
}));
});

describe('on a parent element', () => {
it('applies the active class when any child link is active', async(async () => {
const template = `
<li uiSrefActive="active">
<a uiSref="statea">State A</a>
<a uiSref="statec">State C</a>
</li>
`;
@Component({ template })
class TestComponent {}

const fixture = initialize(TestComponent, [{ name: 'statea' }, { name: 'stateb' }, { name: 'statec' }]);

const des = fixture.debugElement.queryAll(By.directive(UISrefActive));
const router = fixture.debugElement.injector.get(UIRouter);

await router.stateService.go('statea').then(tick);
expect(des[0].nativeElement.classList).toContain('active');

await router.stateService.go('stateb').then(tick);
expect(des[0].nativeElement.classList).not.toContain('active');

await router.stateService.go('statec').then(tick);
expect(des[0].nativeElement.classList).toContain('active');
}));

// Test for https://github.com/ui-router/angular/issues/760
it('can dynamically add or remove nested uiSref', async(async () => {
const template = `
<li id="parent" uiSrefActive="active">
<a uiSref="statea"></a>
<a uiSref="stateb" *ngIf="show"></a>
</li>
`;
@Component({ template })
class TestComponent {
public show = false;
}

const states = [{ name: 'statea' }, { name: 'stateb' }, { name: 'statec' }];
const fixture = initialize(TestComponent, states);

const des = fixture.debugElement.queryAll(By.directive(UISrefActive));
const router = fixture.debugElement.injector.get(UIRouter);

await router.stateService.go('statea').then(tick);
expect(des[0].nativeElement.classList).toContain('active');

fixture.componentInstance.show = true;
fixture.detectChanges();

await router.stateService.go('stateb').then(tick);
expect(des[0].nativeElement.classList).toContain('active');

await router.stateService.go('statec').then(tick);
expect(des[0].nativeElement.classList).not.toContain('active');
}));
});
});

0 comments on commit 8d35dc1

Please sign in to comment.