Skip to content

Commit

Permalink
fix(tabs): fix infinite tab loop (#6663)
Browse files Browse the repository at this point in the history
Fixes #4639
  • Loading branch information
amcdnl authored and jelbourn committed Sep 1, 2017
1 parent 9acab86 commit 67e02b0
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 8 deletions.
19 changes: 19 additions & 0 deletions src/lib/tabs/tab-group.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
16 changes: 8 additions & 8 deletions src/lib/tabs/tab-group.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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<number> {
return map.call(this.selectChange, event => event.index);
}
@Output() selectedIndexChange: EventEmitter<number> = new EventEmitter();

/** Event emitted when focus has changed within a tab group. */
@Output() focusChange: EventEmitter<MdTabChangeEvent> = new EventEmitter<MdTabChangeEvent>();
Expand All @@ -157,16 +153,20 @@ 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));

// If there is a change in selected index, emit a change event. Should not trigger if
// 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.
Expand Down

0 comments on commit 67e02b0

Please sign in to comment.