From 4d2ab31317b6dc39d6ce13d5c6f62a33f9e70b82 Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Thu, 17 Apr 2025 09:30:30 +0200 Subject: [PATCH] fix(multiple): use DI token for tag name Reads the tag name through DI, instead of going through the DOM which should be more SSR-friendly. --- src/cdk-experimental/combobox/combobox.ts | 6 ++++-- src/material/badge/badge.ts | 6 +++++- src/material/chips/chip.ts | 7 ++++--- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/cdk-experimental/combobox/combobox.ts b/src/cdk-experimental/combobox/combobox.ts index 450db6d1459d..646957d8a735 100644 --- a/src/cdk-experimental/combobox/combobox.ts +++ b/src/cdk-experimental/combobox/combobox.ts @@ -23,6 +23,7 @@ import { Directive, ElementRef, EventEmitter, + HOST_TAG_NAME, InjectionToken, Injector, Input, @@ -60,6 +61,7 @@ export const CDK_COMBOBOX = new InjectionToken('CDK_COMBOBOX'); providers: [{provide: CDK_COMBOBOX, useExisting: CdkCombobox}], }) export class CdkCombobox implements OnDestroy { + private readonly _tagName = inject(HOST_TAG_NAME); private readonly _elementRef = inject>(ElementRef); private readonly _overlay = inject(Overlay); protected readonly _viewContainerRef = inject(ViewContainerRef); @@ -245,8 +247,8 @@ export class CdkCombobox implements OnDestroy { private _isTextTrigger() { // TODO: Should check if the trigger is contenteditable. - const tagName = this._elementRef.nativeElement.tagName.toLowerCase(); - return tagName === 'input' || tagName === 'textarea' ? true : false; + const tagName = this._tagName.toLowerCase(); + return tagName === 'input' || tagName === 'textarea'; } private _getOverlayConfig() { diff --git a/src/material/badge/badge.ts b/src/material/badge/badge.ts index 2cbb6e18da03..ee3fd199ff83 100644 --- a/src/material/badge/badge.ts +++ b/src/material/badge/badge.ts @@ -21,6 +21,7 @@ import { OnInit, Renderer2, ViewEncapsulation, + HOST_TAG_NAME, } from '@angular/core'; import {_animationsDisabled, ThemePalette} from '../core'; import {_CdkPrivateStyleLoader, _VisuallyHiddenLoader} from '@angular/cdk/private'; @@ -156,15 +157,18 @@ export class MatBadge implements OnInit, OnDestroy { if (typeof ngDevMode === 'undefined' || ngDevMode) { const nativeElement = this._elementRef.nativeElement; + if (nativeElement.nodeType !== nativeElement.ELEMENT_NODE) { throw Error('matBadge must be attached to an element node.'); } + const tagName = inject(HOST_TAG_NAME); + // Heads-up for developers to avoid putting matBadge on // as it is aria-hidden by default docs mention this at: // https://material.angular.io/components/badge/overview#accessibility if ( - nativeElement.tagName.toLowerCase() === 'mat-icon' && + tagName.toLowerCase() === 'mat-icon' && nativeElement.getAttribute('aria-hidden') === 'true' ) { console.warn( diff --git a/src/material/chips/chip.ts b/src/material/chips/chip.ts index 883e6f280fca..b597a9fb18e7 100644 --- a/src/material/chips/chip.ts +++ b/src/material/chips/chip.ts @@ -21,6 +21,7 @@ import { DoCheck, ElementRef, EventEmitter, + HOST_TAG_NAME, Injector, Input, NgZone, @@ -90,6 +91,7 @@ export interface MatChipEvent { export class MatChip implements OnInit, AfterViewInit, AfterContentInit, DoCheck, OnDestroy { _changeDetectorRef = inject(ChangeDetectorRef); _elementRef = inject>(ElementRef); + private readonly _tagName = inject(HOST_TAG_NAME); protected _ngZone = inject(NgZone); private _focusMonitor = inject(FocusMonitor); private _globalRippleOptions = inject(MAT_RIPPLE_GLOBAL_OPTIONS, { @@ -256,10 +258,9 @@ export class MatChip implements OnInit, AfterViewInit, AfterContentInit, DoCheck ngOnInit() { // This check needs to happen in `ngOnInit` so the overridden value of // `basicChipAttrName` coming from base classes can be picked up. - const element = this._elementRef.nativeElement; this._isBasicChip = - element.hasAttribute(this.basicChipAttrName) || - element.tagName.toLowerCase() === this.basicChipAttrName; + this._elementRef.nativeElement.hasAttribute(this.basicChipAttrName) || + this._tagName.toLowerCase() === this.basicChipAttrName; } ngAfterViewInit() {