From 6603bd5ec6891dcc2a4c0d5ab3b5a9cfc8eec068 Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Thu, 21 Apr 2022 16:24:31 +0200 Subject: [PATCH] fix(material-experimental/mdc-snack-bar): avoid querying the DOM on each change detection (#24770) Currently the MDC snack bar container is querying the DOM on each change detection in order to apply the correct class to the content. We don't need to do this so frequently since everything is set after the portal content has been attached. (cherry picked from commit d3428ba5a20a6780c90f68403806f8e8acc41414) --- .../mdc-snack-bar/snack-bar-container.ts | 36 +++++++++++-------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/src/material-experimental/mdc-snack-bar/snack-bar-container.ts b/src/material-experimental/mdc-snack-bar/snack-bar-container.ts index afdc9fc72a77..11fd467869e6 100644 --- a/src/material-experimental/mdc-snack-bar/snack-bar-container.ts +++ b/src/material-experimental/mdc-snack-bar/snack-bar-container.ts @@ -14,7 +14,6 @@ import { TemplatePortal, } from '@angular/cdk/portal'; import { - AfterViewChecked, ChangeDetectionStrategy, Component, ComponentRef, @@ -65,7 +64,7 @@ const MDC_SNACKBAR_LABEL_CLASS = 'mdc-snackbar__label'; }) export class MatSnackBarContainer extends BasePortalOutlet - implements _SnackBarContainer, AfterViewChecked, OnDestroy + implements _SnackBarContainer, OnDestroy { /** The number of milliseconds to wait before announcing the snack bar's content. */ private readonly _announceDelay: number = 150; @@ -157,17 +156,6 @@ export class MatSnackBarContainer this._mdcFoundation.setTimeoutMs(-1); } - ngAfterViewChecked() { - // Check to see if the attached component or template uses the MDC template structure, - // specifically the MDC label. If not, the container should apply the MDC label class to this - // component's label container, which will apply MDC's label styles to the attached view. - if (!this._label.nativeElement.querySelector(`.${MDC_SNACKBAR_LABEL_CLASS}`)) { - this._label.nativeElement.classList.add(MDC_SNACKBAR_LABEL_CLASS); - } else { - this._label.nativeElement.classList.remove(MDC_SNACKBAR_LABEL_CLASS); - } - } - /** Makes sure the exit callbacks have been invoked when the element is destroyed. */ ngOnDestroy() { this._mdcFoundation.close(); @@ -202,14 +190,18 @@ export class MatSnackBarContainer attachComponentPortal(portal: ComponentPortal): ComponentRef { this._assertNotAttached(); this._applySnackBarClasses(); - return this._portalOutlet.attachComponentPortal(portal); + const componentRef = this._portalOutlet.attachComponentPortal(portal); + this._applyLabelClass(); + return componentRef; } /** Attach a template portal as content to this snack bar container. */ attachTemplatePortal(portal: TemplatePortal): EmbeddedViewRef { this._assertNotAttached(); this._applySnackBarClasses(); - return this._portalOutlet.attachTemplatePortal(portal); + const viewRef = this._portalOutlet.attachTemplatePortal(portal); + this._applyLabelClass(); + return viewRef; } private _setClass(cssClass: string, active: boolean) { @@ -269,4 +261,18 @@ export class MatSnackBarContainer }); } } + + /** Applies the correct CSS class to the label based on its content. */ + private _applyLabelClass() { + // Check to see if the attached component or template uses the MDC template structure, + // specifically the MDC label. If not, the container should apply the MDC label class to this + // component's label container, which will apply MDC's label styles to the attached view. + const label = this._label.nativeElement; + + if (!label.querySelector(`.${MDC_SNACKBAR_LABEL_CLASS}`)) { + label.classList.add(MDC_SNACKBAR_LABEL_CLASS); + } else { + label.classList.remove(MDC_SNACKBAR_LABEL_CLASS); + } + } }