From 67e02b0483fd4304022b84a30227c7b28e1b4ca6 Mon Sep 17 00:00:00 2001 From: Austin Date: Fri, 1 Sep 2017 09:58:27 -0500 Subject: [PATCH] fix(tabs): fix infinite tab loop (#6663) Fixes #4639 --- src/lib/tabs/tab-group.spec.ts | 19 +++++++++++++++++++ src/lib/tabs/tab-group.ts | 16 ++++++++-------- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/src/lib/tabs/tab-group.spec.ts b/src/lib/tabs/tab-group.spec.ts index d30a5835a8b6..439367351a20 100644 --- a/src/lib/tabs/tab-group.spec.ts +++ b/src/lib/tabs/tab-group.spec.ts @@ -70,6 +70,25 @@ describe('MdTabGroup', () => { }); })); + it('should set to correct tab on fast change', async(() => { + let component = fixture.componentInstance; + component.selectedIndex = 0; + fixture.detectChanges(); + + setTimeout(() => { + component.selectedIndex = 1; + fixture.detectChanges(); + + setTimeout(() => { + component.selectedIndex = 0; + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect(component.selectedIndex).toBe(0); + }); + }, 1); + }, 1); + })); + it('should change tabs based on selectedIndex', fakeAsync(() => { let component = fixture.componentInstance; let tabComponent = fixture.debugElement.query(By.css('md-tab-group')).componentInstance; diff --git a/src/lib/tabs/tab-group.ts b/src/lib/tabs/tab-group.ts index f3d40a01b0ec..8c3bf330cc40 100644 --- a/src/lib/tabs/tab-group.ts +++ b/src/lib/tabs/tab-group.ts @@ -25,8 +25,6 @@ import { ViewEncapsulation, } from '@angular/core'; import {coerceBooleanProperty} from '@angular/cdk/coercion'; -import {map} from '@angular/cdk/rxjs'; -import {Observable} from 'rxjs/Observable'; import {Subscription} from 'rxjs/Subscription'; import {MdTab} from './tab'; import {merge} from 'rxjs/observable/merge'; @@ -131,9 +129,7 @@ export class MdTabGroup extends _MdTabGroupMixinBase implements AfterContentInit private _backgroundColor: ThemePalette; /** Output to enable support for two-way binding on `[(selectedIndex)]` */ - @Output() get selectedIndexChange(): Observable { - return map.call(this.selectChange, event => event.index); - } + @Output() selectedIndexChange: EventEmitter = new EventEmitter(); /** Event emitted when focus has changed within a tab group. */ @Output() focusChange: EventEmitter = new EventEmitter(); @@ -157,9 +153,10 @@ export class MdTabGroup extends _MdTabGroupMixinBase implements AfterContentInit * a new selected tab should transition in (from the left or right). */ ngAfterContentChecked(): void { - // Clamp the next selected index to the bounds of 0 and the tabs length. Note the `|| 0`, which - // ensures that values like NaN can't get through and which would otherwise throw the - // component into an infinite loop (since Math.max(NaN, 0) === NaN). + // Clamp the next selected index to the boundsof 0 and the tabs length. + // Note the `|| 0`, which ensures that values like NaN can't get through + // and which would otherwise throw the component into an infinite loop + // (since Math.max(NaN, 0) === NaN). let indexToSelect = this._indexToSelect = Math.min(this._tabs.length - 1, Math.max(this._indexToSelect || 0, 0)); @@ -167,6 +164,9 @@ export class MdTabGroup extends _MdTabGroupMixinBase implements AfterContentInit // the selected index has not yet been initialized. if (this._selectedIndex != indexToSelect && this._selectedIndex != null) { this.selectChange.emit(this._createChangeEvent(indexToSelect)); + // Emitting this value after change detection has run + // since the checked content may contain this variable' + Promise.resolve().then(() => this.selectedIndexChange.emit(indexToSelect)); } // Setup the position for each tab and optionally setup an origin on the next selected tab.