diff --git a/src/lib/tabs/tab-header.html b/src/lib/tabs/tab-header.html index ad18fb49bbad..a784f2760705 100644 --- a/src/lib/tabs/tab-header.html +++ b/src/lib/tabs/tab-header.html @@ -8,7 +8,7 @@
-
+
diff --git a/src/lib/tabs/tab-header.ts b/src/lib/tabs/tab-header.ts index 930ffde09c50..7a0abd9b8228 100644 --- a/src/lib/tabs/tab-header.ts +++ b/src/lib/tabs/tab-header.ts @@ -5,7 +5,13 @@ import { NgZone, QueryList, ElementRef, - ViewEncapsulation, ContentChildren, Output, EventEmitter, Optional + ViewEncapsulation, + ContentChildren, + Output, + EventEmitter, + Optional, + AfterContentChecked, + AfterContentInit, } from '@angular/core'; import {RIGHT_ARROW, LEFT_ARROW, ENTER, Dir, LayoutDirection} from '../core'; import {MdTabLabelWrapper} from './tab-label-wrapper'; @@ -44,7 +50,7 @@ const EXAGGERATED_OVERSCROLL = 60; '[class.md-tab-header-rtl]': "_getLayoutDirection() == 'rtl'", } }) -export class MdTabHeader { +export class MdTabHeader implements AfterContentChecked, AfterContentInit { @ContentChildren(MdTabLabelWrapper) _labelWrappers: QueryList; @ViewChild(MdInkBar) _inkBar: MdInkBar; @@ -106,12 +112,12 @@ export class MdTabHeader { this._tabLabelCount = this._labelWrappers.length; } - // If the selected index has changed, scroll to the label and check if the scrolling controls // should be disabled. if (this._selectedIndexChanged) { this._scrollToLabel(this._selectedIndex); this._checkScrollingControls(); + this._alignInkBarToSelectedTab(); this._selectedIndexChanged = false; } @@ -123,18 +129,6 @@ export class MdTabHeader { } } - /** - * Waits one frame for the view to update, then updates the ink bar and scroll. - * Note: This must be run outside of the zone or it will create an infinite change detection loop. - */ - ngAfterViewChecked(): void { - this._zone.runOutsideAngular(() => { - window.requestAnimationFrame(() => { - this._alignInkBarToSelectedTab(); - }); - }); - } - _handleKeydown(event: KeyboardEvent) { switch (event.keyCode) { case RIGHT_ARROW: @@ -149,6 +143,21 @@ export class MdTabHeader { } } + /** + * Aligns the ink bar to the selected tab on load. + */ + ngAfterContentInit() { + this._alignInkBarToSelectedTab(); + } + + /** + * Callback for when the MutationObserver detects that the content has changed. + */ + _onContentChanges() { + this._updatePagination(); + this._alignInkBarToSelectedTab(); + } + /** * Updating the view whether pagination should be enabled or not */ @@ -178,7 +187,7 @@ export class MdTabHeader { _isValidIndex(index: number): boolean { if (!this._labelWrappers) { return true; } - const tab = this._labelWrappers.toArray()[index]; + const tab = this._labelWrappers ? this._labelWrappers.toArray()[index] : null; return tab && !tab.disabled; } @@ -282,7 +291,10 @@ export class MdTabHeader { * should be called sparingly. */ _scrollToLabel(labelIndex: number) { - const selectedLabel = this._labelWrappers.toArray()[labelIndex]; + const selectedLabel = this._labelWrappers + ? this._labelWrappers.toArray()[labelIndex] + : null; + if (!selectedLabel) { return; } // The view length is the visible width of the tab labels. @@ -359,6 +371,11 @@ export class MdTabHeader { const selectedLabelWrapper = this._labelWrappers && this._labelWrappers.length ? this._labelWrappers.toArray()[this.selectedIndex].elementRef.nativeElement : null; - this._inkBar.alignToElement(selectedLabelWrapper); + + this._zone.runOutsideAngular(() => { + requestAnimationFrame(() => { + this._inkBar.alignToElement(selectedLabelWrapper); + }); + }); } }