diff --git a/src/material/button/button-base.ts b/src/material/button/button-base.ts index 85d998f7c541..8d1791b731a6 100644 --- a/src/material/button/button-base.ts +++ b/src/material/button/button-base.ts @@ -45,34 +45,30 @@ export interface MatButtonConfig { /** Injection token that can be used to provide the default options the button component. */ export const MAT_BUTTON_CONFIG = new InjectionToken('MAT_BUTTON_CONFIG'); -/** Shared host configuration for all buttons */ -export const MAT_BUTTON_HOST = { - '[attr.disabled]': '_getDisabledAttribute()', - '[attr.aria-disabled]': '_getAriaDisabled()', - '[class.mat-mdc-button-disabled]': 'disabled', - '[class.mat-mdc-button-disabled-interactive]': 'disabledInteractive', - '[class._mat-animation-noopable]': '_animationMode === "NoopAnimations"', - // MDC automatically applies the primary theme color to the button, but we want to support - // an unthemed version. If color is undefined, apply a CSS class that makes it easy to - // select and style this "theme". - '[class.mat-unthemed]': '!color', - // Add a class that applies to all buttons. This makes it easier to target if somebody - // wants to target all Material buttons. - '[class.mat-mdc-button-base]': 'true', - '[class]': 'color ? "mat-" + color : ""', - '[attr.tabindex]': '_getTabIndex()', -}; - function transformTabIndex(value: unknown): number | undefined { return value == null ? undefined : numberAttribute(value); } -/** Base class for all buttons. */ -@Directive() +/** Base class for all buttons. */ +@Directive({ + host: { + // Add a class that applies to all buttons. This makes it easier to target if somebody + // wants to target all Material buttons. + 'class': 'mat-mdc-button-base', + '[class]': 'color ? "mat-" + color : ""', + '[attr.disabled]': '_getDisabledAttribute()', + '[attr.aria-disabled]': '_getAriaDisabled()', + '[attr.tabindex]': '_getTabIndex()', + '[class.mat-mdc-button-disabled]': 'disabled', + '[class.mat-mdc-button-disabled-interactive]': 'disabledInteractive', + '[class.mat-unthemed]': '!color', + '[class._mat-animation-noopable]': '_animationMode === "NoopAnimations"', + }, +}) export class MatButtonBase implements AfterViewInit, OnDestroy { _elementRef = inject>(ElementRef); - _ngZone = inject(NgZone); - _animationMode = inject(ANIMATION_MODULE_TYPE, {optional: true}); + protected _ngZone = inject(NgZone); + protected _animationMode = inject(ANIMATION_MODULE_TYPE, {optional: true}); protected readonly _config = inject(MAT_BUTTON_CONFIG, {optional: true}); private readonly _focusMonitor = inject(FocusMonitor); diff --git a/src/material/button/button.ts b/src/material/button/button.ts index 0fcb4661ab6d..8883e1d27664 100644 --- a/src/material/button/button.ts +++ b/src/material/button/button.ts @@ -7,7 +7,7 @@ */ import {ChangeDetectionStrategy, Component, Input, ViewEncapsulation} from '@angular/core'; -import {MAT_BUTTON_HOST, MatButtonAppearance, MatButtonBase} from './button-base'; +import {MatButtonAppearance, MatButtonBase} from './button-base'; /** * Classes that need to be set for each appearance of the button. @@ -32,7 +32,9 @@ const APPEARANCE_CLASSES: Map = new Map( `, templateUrl: 'button.html', styleUrls: ['button.css', 'button-high-contrast.css'], - host: MAT_BUTTON_HOST, + host: { + 'class': 'mdc-button', + }, exportAs: 'matButton, matAnchor', encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, @@ -54,11 +56,7 @@ export class MatButton extends MatButtonBase { constructor() { super(); - const element = this._elementRef.nativeElement; - const inferredAppearance = _inferAppearance(element); - - // This class is common across all the appearances so we add it ahead of time. - element.classList.add('mdc-button'); + const inferredAppearance = _inferAppearance(this._elementRef.nativeElement); // Only set the appearance if we managed to infer it from the static attributes, rather than // doing something like `setAppearance(inferredAppearance || 'text')`, because doing so can diff --git a/src/material/button/fab.ts b/src/material/button/fab.ts index ce5ab638a937..1d694dec4103 100644 --- a/src/material/button/fab.ts +++ b/src/material/button/fab.ts @@ -16,7 +16,7 @@ import { inject, } from '@angular/core'; -import {MAT_BUTTON_HOST, MatButtonBase} from './button-base'; +import {MatButtonBase} from './button-base'; import {ThemePalette} from '../core'; /** Default FAB options that can be overridden. */ @@ -67,7 +67,7 @@ const defaults = MAT_FAB_DEFAULT_OPTIONS_FACTORY(); templateUrl: 'button.html', styleUrl: 'fab.css', host: { - ...MAT_BUTTON_HOST, + 'class': 'mdc-fab mat-mdc-fab-base mat-mdc-fab', '[class.mdc-fab--extended]': 'extended', '[class.mat-mdc-extended-fab]': 'extended', }, @@ -86,8 +86,6 @@ export class MatFabButton extends MatButtonBase { constructor() { super(); - const element = this._elementRef.nativeElement; - element.classList.add('mdc-fab', 'mat-mdc-fab-base', 'mat-mdc-fab'); this._options = this._options || defaults; this.color = this._options!.color || defaults.color; } @@ -102,7 +100,9 @@ export class MatFabButton extends MatButtonBase { selector: `button[mat-mini-fab], a[mat-mini-fab], button[matMiniFab], a[matMiniFab]`, templateUrl: 'button.html', styleUrl: 'fab.css', - host: MAT_BUTTON_HOST, + host: { + 'class': 'mdc-fab mat-mdc-fab-base mdc-fab--mini mat-mdc-mini-fab', + }, exportAs: 'matButton, matAnchor', encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, @@ -116,8 +116,6 @@ export class MatMiniFabButton extends MatButtonBase { constructor() { super(); - const element = this._elementRef.nativeElement; - element.classList.add('mdc-fab', 'mat-mdc-fab-base', 'mdc-fab--mini', 'mat-mdc-mini-fab'); this._options = this._options || defaults; this.color = this._options!.color || defaults.color; } diff --git a/src/material/button/icon-button.ts b/src/material/button/icon-button.ts index 90cf49864c55..8a3fd22671fb 100644 --- a/src/material/button/icon-button.ts +++ b/src/material/button/icon-button.ts @@ -7,7 +7,7 @@ */ import {ChangeDetectionStrategy, Component, ViewEncapsulation} from '@angular/core'; -import {MAT_BUTTON_HOST, MatButtonBase} from './button-base'; +import {MatButtonBase} from './button-base'; /** * Material Design icon button component. This type of button displays a single interactive icon for @@ -18,7 +18,9 @@ import {MAT_BUTTON_HOST, MatButtonBase} from './button-base'; selector: `button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]`, templateUrl: 'icon-button.html', styleUrls: ['icon-button.css', 'button-high-contrast.css'], - host: MAT_BUTTON_HOST, + host: { + 'class': 'mdc-icon-button mat-mdc-icon-button', + }, exportAs: 'matButton, matAnchor', encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, @@ -28,9 +30,7 @@ export class MatIconButton extends MatButtonBase { constructor() { super(); - const element = this._elementRef.nativeElement; - element.classList.add('mdc-icon-button', 'mat-mdc-icon-button'); - this._rippleLoader.configureRipple(element, {centered: true}); + this._rippleLoader.configureRipple(this._elementRef.nativeElement, {centered: true}); } } diff --git a/tslint.json b/tslint.json index 001155ea6094..71cbdfc9d465 100644 --- a/tslint.json +++ b/tslint.json @@ -111,13 +111,6 @@ } ], "Directive": [ - { - "argument": 0, - "properties": { - "!host": "\\[class\\]" - }, - "excludeFiles": ["**/dev-app/**"] - }, // Enforce standalone even in the dev-app. { "argument": 0,