From fde47744c11130b19c1a4e8a868e24088761b779 Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Thu, 31 Aug 2023 09:52:41 +0200 Subject: [PATCH] refactor(material/slide-toggle): remove mixin class usages Replaces mixin class usages in the slide toggle with input transforms. --- src/material/slide-toggle/BUILD.bazel | 1 - src/material/slide-toggle/slide-toggle.html | 2 +- src/material/slide-toggle/slide-toggle.ts | 85 ++++++------------- .../public_api_guard/material/slide-toggle.md | 35 +++++--- 4 files changed, 47 insertions(+), 76 deletions(-) diff --git a/src/material/slide-toggle/BUILD.bazel b/src/material/slide-toggle/BUILD.bazel index b74956ffb5c1..2315867b1723 100644 --- a/src/material/slide-toggle/BUILD.bazel +++ b/src/material/slide-toggle/BUILD.bazel @@ -21,7 +21,6 @@ ng_module( ), assets = [":slide_toggle_scss"] + glob(["**/*.html"]), deps = [ - "//src/cdk/coercion", "//src/material/core", "@npm//@angular/animations", "@npm//@angular/common", diff --git a/src/material/slide-toggle/slide-toggle.html b/src/material/slide-toggle/slide-toggle.html index fb83dc215e92..d3393e326654 100644 --- a/src/material/slide-toggle/slide-toggle.html +++ b/src/material/slide-toggle/slide-toggle.html @@ -8,7 +8,7 @@ [class.mdc-switch--unselected]="!checked" [class.mdc-switch--checked]="checked" [class.mdc-switch--disabled]="disabled" - [tabIndex]="tabIndex" + [tabIndex]="disabled ? -1 : tabIndex" [disabled]="disabled" [attr.id]="buttonId" [attr.name]="name" diff --git a/src/material/slide-toggle/slide-toggle.ts b/src/material/slide-toggle/slide-toggle.ts index 2d118799488a..4c626746820a 100644 --- a/src/material/slide-toggle/slide-toggle.ts +++ b/src/material/slide-toggle/slide-toggle.ts @@ -9,6 +9,7 @@ import { AfterContentInit, Attribute, + booleanAttribute, ChangeDetectionStrategy, ChangeDetectorRef, Component, @@ -17,12 +18,14 @@ import { forwardRef, Inject, Input, + numberAttribute, OnDestroy, Optional, Output, ViewChild, ViewEncapsulation, } from '@angular/core'; +import {ThemePalette} from '@angular/material/core'; import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms'; import {ANIMATION_MODULE_TYPE} from '@angular/platform-browser/animations'; import {FocusMonitor} from '@angular/cdk/a11y'; @@ -30,17 +33,6 @@ import { MAT_SLIDE_TOGGLE_DEFAULT_OPTIONS, MatSlideToggleDefaultOptions, } from './slide-toggle-config'; -import { - CanColor, - CanDisable, - CanDisableRipple, - HasTabIndex, - mixinColor, - mixinDisabled, - mixinDisableRipple, - mixinTabIndex, -} from '@angular/material/core'; -import {BooleanInput, coerceBooleanProperty} from '@angular/cdk/coercion'; /** @docs-private */ export const MAT_SLIDE_TOGGLE_VALUE_ACCESSOR = { @@ -62,20 +54,6 @@ export class MatSlideToggleChange { // Increasing integer for generating unique ids for slide-toggle components. let nextUniqueId = 0; -// Boilerplate for applying mixins to MatSlideToggle. -/** @docs-private */ -const _MatSlideToggleMixinBase = mixinTabIndex( - mixinColor( - mixinDisableRipple( - mixinDisabled( - class { - constructor(public _elementRef: ElementRef) {} - }, - ), - ), - ), -); - @Component({ selector: 'mat-slide-toggle', templateUrl: 'slide-toggle.html', @@ -92,28 +70,18 @@ const _MatSlideToggleMixinBase = mixinTabIndex( '[class.mat-mdc-slide-toggle-focused]': '_focused', '[class.mat-mdc-slide-toggle-checked]': 'checked', '[class._mat-animation-noopable]': '_noopAnimations', + '[class]': 'color ? "mat-" + color : ""', }, exportAs: 'matSlideToggle', encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, providers: [MAT_SLIDE_TOGGLE_VALUE_ACCESSOR], }) -export class MatSlideToggle - extends _MatSlideToggleMixinBase - implements - OnDestroy, - AfterContentInit, - ControlValueAccessor, - CanDisable, - CanColor, - HasTabIndex, - CanDisableRipple -{ +export class MatSlideToggle implements OnDestroy, AfterContentInit, ControlValueAccessor { private _onChange = (_: any) => {}; private _onTouched = () => {}; private _uniqueId: string; - private _required: boolean = false; private _checked: boolean = false; private _createChangeEvent(isChecked: boolean) { @@ -160,35 +128,33 @@ export class MatSlideToggle @Input('aria-describedby') ariaDescribedby: string; /** Whether the slide-toggle is required. */ - @Input() - get required(): boolean { - return this._required; - } + @Input({transform: booleanAttribute}) required: boolean; - set required(value: BooleanInput) { - this._required = coerceBooleanProperty(value); - } + /** Palette color of slide toggle. */ + @Input() color: ThemePalette; + + /** Whether the slide toggle is disabled. */ + @Input({transform: booleanAttribute}) disabled: boolean; + + /** Whether the slide toggle has a ripple. */ + @Input({transform: booleanAttribute}) disableRipple: boolean; + + /** Tabindex of slide toggle. */ + @Input({transform: (value: unknown) => (value == null ? 0 : numberAttribute(value))}) + tabIndex: number = 0; /** Whether the slide-toggle element is checked or not. */ - @Input() + @Input({transform: booleanAttribute}) get checked(): boolean { return this._checked; } - - set checked(value: BooleanInput) { - this._checked = coerceBooleanProperty(value); + set checked(value: boolean) { + this._checked = value; this._changeDetectorRef.markForCheck(); } /** Whether to hide the icon inside of the slide toggle. */ - @Input() - get hideIcon(): boolean { - return this._hideIcon; - } - set hideIcon(value: BooleanInput) { - this._hideIcon = coerceBooleanProperty(value); - } - private _hideIcon = false; + @Input({transform: booleanAttribute}) hideIcon: boolean; /** An event will be dispatched each time the slide-toggle changes its value. */ @Output() readonly change = new EventEmitter(); @@ -206,19 +172,18 @@ export class MatSlideToggle } constructor( - elementRef: ElementRef, + private _elementRef: ElementRef, protected _focusMonitor: FocusMonitor, protected _changeDetectorRef: ChangeDetectorRef, @Attribute('tabindex') tabIndex: string, @Inject(MAT_SLIDE_TOGGLE_DEFAULT_OPTIONS) public defaults: MatSlideToggleDefaultOptions, @Optional() @Inject(ANIMATION_MODULE_TYPE) animationMode?: string, ) { - super(elementRef); this.tabIndex = parseInt(tabIndex) || 0; - this.color = this.defaultColor = defaults.color || 'accent'; + this.color = defaults.color || 'accent'; this._noopAnimations = animationMode === 'NoopAnimations'; this.id = this._uniqueId = `mat-mdc-slide-toggle-${++nextUniqueId}`; - this._hideIcon = defaults.hideIcon ?? false; + this.hideIcon = defaults.hideIcon ?? false; this._labelId = this._uniqueId + '-label'; } diff --git a/tools/public_api_guard/material/slide-toggle.md b/tools/public_api_guard/material/slide-toggle.md index d76f9b06d299..26660b61f369 100644 --- a/tools/public_api_guard/material/slide-toggle.md +++ b/tools/public_api_guard/material/slide-toggle.md @@ -4,20 +4,13 @@ ```ts -import { _AbstractConstructor } from '@angular/material/core'; import { AfterContentInit } from '@angular/core'; -import { BooleanInput } from '@angular/cdk/coercion'; -import { CanColor } from '@angular/material/core'; -import { CanDisable } from '@angular/material/core'; -import { CanDisableRipple } from '@angular/material/core'; import { ChangeDetectorRef } from '@angular/core'; import { CheckboxRequiredValidator } from '@angular/forms'; -import { _Constructor } from '@angular/material/core'; import { ControlValueAccessor } from '@angular/forms'; import { ElementRef } from '@angular/core'; import { EventEmitter } from '@angular/core'; import { FocusMonitor } from '@angular/cdk/a11y'; -import { HasTabIndex } from '@angular/material/core'; import * as i0 from '@angular/core'; import * as i3 from '@angular/material/core'; import * as i4 from '@angular/common'; @@ -41,8 +34,8 @@ export const MAT_SLIDE_TOGGLE_VALUE_ACCESSOR: { }; // @public (undocumented) -export class MatSlideToggle extends _MatSlideToggleMixinBase implements OnDestroy, AfterContentInit, ControlValueAccessor, CanDisable, CanColor, HasTabIndex, CanDisableRipple { - constructor(elementRef: ElementRef, _focusMonitor: FocusMonitor, _changeDetectorRef: ChangeDetectorRef, tabIndex: string, defaults: MatSlideToggleDefaultOptions, animationMode?: string); +export class MatSlideToggle implements OnDestroy, AfterContentInit, ControlValueAccessor { + constructor(_elementRef: ElementRef, _focusMonitor: FocusMonitor, _changeDetectorRef: ChangeDetectorRef, tabIndex: string, defaults: MatSlideToggleDefaultOptions, animationMode?: string); ariaDescribedby: string; ariaLabel: string | null; ariaLabelledby: string | null; @@ -51,9 +44,12 @@ export class MatSlideToggle extends _MatSlideToggleMixinBase implements OnDestro // (undocumented) protected _changeDetectorRef: ChangeDetectorRef; get checked(): boolean; - set checked(value: BooleanInput); + set checked(value: boolean); + color: ThemePalette; // (undocumented) defaults: MatSlideToggleDefaultOptions; + disabled: boolean; + disableRipple: boolean; protected _emitChangeEvent(): void; focus(): void; _focused: boolean; @@ -62,24 +58,35 @@ export class MatSlideToggle extends _MatSlideToggleMixinBase implements OnDestro // (undocumented) _getAriaLabelledBy(): string | null; _handleClick(): void; - get hideIcon(): boolean; - set hideIcon(value: BooleanInput); + hideIcon: boolean; id: string; get inputId(): string; _labelId: string; labelPosition: 'before' | 'after'; name: string | null; // (undocumented) + static ngAcceptInputType_checked: unknown; + // (undocumented) + static ngAcceptInputType_disabled: unknown; + // (undocumented) + static ngAcceptInputType_disableRipple: unknown; + // (undocumented) + static ngAcceptInputType_hideIcon: unknown; + // (undocumented) + static ngAcceptInputType_required: unknown; + // (undocumented) + static ngAcceptInputType_tabIndex: unknown; + // (undocumented) ngAfterContentInit(): void; // (undocumented) ngOnDestroy(): void; _noopAnimations: boolean; registerOnChange(fn: any): void; registerOnTouched(fn: any): void; - get required(): boolean; - set required(value: BooleanInput); + required: boolean; setDisabledState(isDisabled: boolean): void; _switchElement: ElementRef; + tabIndex: number; toggle(): void; readonly toggleChange: EventEmitter; writeValue(value: any): void;