Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(tabs): avoid hitting change detection if text content hasn't changed #14251

Merged
merged 1 commit into from
Nov 28, 2018
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
33 changes: 22 additions & 11 deletions src/lib/tabs/tab-header.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,8 @@ export class MatTabHeader extends _MatTabHeaderMixinBase
/** Used to manage focus between the tabs. */
private _keyManager: FocusKeyManager<MatTabLabelWrapper>;

private _selectedIndex: number = 0;
/** Cached text content of the header. */
private _currentTextContent: string;

/** The index of the active tab. */
@Input()
Expand All @@ -128,6 +129,7 @@ export class MatTabHeader extends _MatTabHeaderMixinBase
this._keyManager.updateActiveItemIndex(value);
}
}
private _selectedIndex: number = 0;

/** Event emitted when the option is selected. */
@Output() readonly selectFocusedIndex = new EventEmitter();
Expand Down Expand Up @@ -237,16 +239,25 @@ export class MatTabHeader extends _MatTabHeaderMixinBase
* Callback for when the MutationObserver detects that the content has changed.
*/
_onContentChanges() {
const zoneCallback = () => {
this.updatePagination();
this._alignInkBarToSelectedTab();
this._changeDetectorRef.markForCheck();
};

// The content observer runs outside the `NgZone` by default, which
// means that we need to bring the callback back in ourselves.
// @breaking-change 8.0.0 Remove null check for `_ngZone` once it's a required parameter.
this._ngZone ? this._ngZone.run(zoneCallback) : zoneCallback();
const textContent = this._elementRef.nativeElement.textContent;

// We need to diff the text content of the header, because the MutationObserver callback
// will fire even if the text content didn't change which is inefficient and is prone
// to infinite loops if a poorly constructed expression is passed in (see #14249).
if (textContent !== this._currentTextContent) {
this._currentTextContent = textContent;

const zoneCallback = () => {
this.updatePagination();
this._alignInkBarToSelectedTab();
this._changeDetectorRef.markForCheck();
};

// The content observer runs outside the `NgZone` by default, which
// means that we need to bring the callback back in ourselves.
// @breaking-change 8.0.0 Remove null check for `_ngZone` once it's a required parameter.
this._ngZone ? this._ngZone.run(zoneCallback) : zoneCallback();
}
}

/**
Expand Down