From fb12a8d6ace8f46a0884365b0d58e251a4da4c94 Mon Sep 17 00:00:00 2001 From: crisbeto Date: Thu, 9 Apr 2020 17:32:02 +0200 Subject: [PATCH] fix(material-experimental/mdc-radio): avoid bundling styles from base radio button The MDC-based radio button currently extends the `MatRadioButton` directly which means that the styles and template from the base will be bundled together with the MDC one. These changes move all of the functionality into an undecorated base class which is then extended by the two button variants. --- src/material-experimental/mdc-radio/radio.ts | 11 ++- src/material/radio/radio.ts | 72 +++++++++++--------- tools/public_api_guard/material/radio.d.ts | 23 ++++--- 3 files changed, 59 insertions(+), 47 deletions(-) diff --git a/src/material-experimental/mdc-radio/radio.ts b/src/material-experimental/mdc-radio/radio.ts index 648071952e57..912b4ec63fe4 100644 --- a/src/material-experimental/mdc-radio/radio.ts +++ b/src/material-experimental/mdc-radio/radio.ts @@ -24,7 +24,7 @@ import { import {MDCRadioAdapter, MDCRadioFoundation} from '@material/radio'; import { MAT_RADIO_DEFAULT_OPTIONS, - MatRadioButton as BaseMatRadioButton, + _MatRadioButtonBase, MatRadioDefaultOptions, MatRadioGroup as BaseMatRadioGroup, } from '@angular/material/radio'; @@ -71,8 +71,8 @@ const RIPPLE_ANIMATION_CONFIG: RippleAnimationConfig = { }) export class MatRadioGroup extends BaseMatRadioGroup { /** Child radio buttons. */ - @ContentChildren(forwardRef(() => MatRadioButton), { descendants: true }) - _radios: QueryList; + @ContentChildren(forwardRef(() => MatRadioButton), {descendants: true}) + _radios: QueryList<_MatRadioButtonBase>; } @Component({ @@ -81,9 +81,6 @@ export class MatRadioGroup extends BaseMatRadioGroup { styleUrls: ['radio.css'], host: { 'class': 'mat-mdc-radio-button', - // Ivy will inherit the mat-radio-button class from the parent class, but we do not want - // this to be applied in the MDC component. Set this explicitly to false so it is not applied. - '[class.mat-radio-button]': 'false', '[attr.id]': 'id', '[class.mat-primary]': 'color === "primary"', '[class.mat-accent]': 'color === "accent"', @@ -102,7 +99,7 @@ export class MatRadioGroup extends BaseMatRadioGroup { encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, }) -export class MatRadioButton extends BaseMatRadioButton implements AfterViewInit, OnDestroy { +export class MatRadioButton extends _MatRadioButtonBase implements AfterViewInit, OnDestroy { private _radioAdapter: MDCRadioAdapter = { addClass: (className: string) => this._setClass(className, true), diff --git a/src/material/radio/radio.ts b/src/material/radio/radio.ts index e64c9da6e7ac..e369966d64dc 100644 --- a/src/material/radio/radio.ts +++ b/src/material/radio/radio.ts @@ -328,38 +328,13 @@ const _MatRadioButtonMixinBase: mixinDisableRipple(mixinTabIndex(MatRadioButtonBase)); /** - * A Material design radio-button. Typically placed inside of `` elements. + * Base class with all of the `MatRadioButton` functionality. + * @docs-private */ -@Component({ - selector: 'mat-radio-button', - templateUrl: 'radio.html', - styleUrls: ['radio.css'], - inputs: ['disableRipple', 'tabIndex'], - encapsulation: ViewEncapsulation.None, - exportAs: 'matRadioButton', - host: { - 'class': 'mat-radio-button', - '[class.mat-radio-checked]': 'checked', - '[class.mat-radio-disabled]': 'disabled', - '[class._mat-animation-noopable]': '_animationMode === "NoopAnimations"', - '[class.mat-primary]': 'color === "primary"', - '[class.mat-accent]': 'color === "accent"', - '[class.mat-warn]': 'color === "warn"', - // Needs to be -1 so the `focus` event still fires. - '[attr.tabindex]': '-1', - '[attr.id]': 'id', - '[attr.aria-label]': 'null', - '[attr.aria-labelledby]': 'null', - '[attr.aria-describedby]': 'null', - // Note: under normal conditions focus shouldn't land on this element, however it may be - // programmatically set, for example inside of a focus trap, in this case we want to forward - // the focus to the native element. - '(focus)': '_inputElement.nativeElement.focus()', - }, - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class MatRadioButton extends _MatRadioButtonMixinBase - implements OnInit, AfterViewInit, OnDestroy, CanDisableRipple, HasTabIndex { +@Directive() +// tslint:disable-next-line:class-name +export abstract class _MatRadioButtonBase extends _MatRadioButtonMixinBase implements OnInit, + AfterViewInit, OnDestroy, CanDisableRipple, HasTabIndex { private _uniqueId: string = `mat-radio-${++nextUniqueId}`; @@ -606,3 +581,38 @@ export class MatRadioButton extends _MatRadioButtonMixinBase static ngAcceptInputType_required: BooleanInput; static ngAcceptInputType_disableRipple: BooleanInput; } + + +/** + * A Material design radio-button. Typically placed inside of `` elements. + */ +@Component({ + selector: 'mat-radio-button', + templateUrl: 'radio.html', + styleUrls: ['radio.css'], + inputs: ['disableRipple', 'tabIndex'], + encapsulation: ViewEncapsulation.None, + exportAs: 'matRadioButton', + host: { + 'class': 'mat-radio-button', + '[class.mat-radio-checked]': 'checked', + '[class.mat-radio-disabled]': 'disabled', + '[class._mat-animation-noopable]': '_animationMode === "NoopAnimations"', + '[class.mat-primary]': 'color === "primary"', + '[class.mat-accent]': 'color === "accent"', + '[class.mat-warn]': 'color === "warn"', + // Needs to be -1 so the `focus` event still fires. + '[attr.tabindex]': '-1', + '[attr.id]': 'id', + '[attr.aria-label]': 'null', + '[attr.aria-labelledby]': 'null', + '[attr.aria-describedby]': 'null', + // Note: under normal conditions focus shouldn't land on this element, however it may be + // programmatically set, for example inside of a focus trap, in this case we want to forward + // the focus to the native element. + '(focus)': '_inputElement.nativeElement.focus()', + }, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class MatRadioButton extends _MatRadioButtonBase { +} diff --git a/tools/public_api_guard/material/radio.d.ts b/tools/public_api_guard/material/radio.d.ts index 95d76092143a..ecb6fc5d9c4d 100644 --- a/tools/public_api_guard/material/radio.d.ts +++ b/tools/public_api_guard/material/radio.d.ts @@ -1,10 +1,4 @@ -export declare const MAT_RADIO_DEFAULT_OPTIONS: InjectionToken; - -export declare function MAT_RADIO_DEFAULT_OPTIONS_FACTORY(): MatRadioDefaultOptions; - -export declare const MAT_RADIO_GROUP_CONTROL_VALUE_ACCESSOR: any; - -export declare class MatRadioButton extends _MatRadioButtonMixinBase implements OnInit, AfterViewInit, OnDestroy, CanDisableRipple, HasTabIndex { +export declare abstract class _MatRadioButtonBase extends _MatRadioButtonMixinBase implements OnInit, AfterViewInit, OnDestroy, CanDisableRipple, HasTabIndex { _animationMode?: string | undefined; protected _changeDetector: ChangeDetectorRef; _inputElement: ElementRef; @@ -42,8 +36,19 @@ export declare class MatRadioButton extends _MatRadioButtonMixinBase implements static ngAcceptInputType_disableRipple: BooleanInput; static ngAcceptInputType_disabled: BooleanInput; static ngAcceptInputType_required: BooleanInput; - static ɵcmp: i0.ɵɵComponentDefWithMeta; - static ɵfac: i0.ɵɵFactoryDef; + static ɵdir: i0.ɵɵDirectiveDefWithMeta<_MatRadioButtonBase, never, never, { "id": "id"; "name": "name"; "ariaLabel": "aria-label"; "ariaLabelledby": "aria-labelledby"; "ariaDescribedby": "aria-describedby"; "checked": "checked"; "value": "value"; "labelPosition": "labelPosition"; "disabled": "disabled"; "required": "required"; "color": "color"; }, { "change": "change"; }, never>; + static ɵfac: i0.ɵɵFactoryDef<_MatRadioButtonBase, [{ optional: true; }, null, null, null, null, { optional: true; }, { optional: true; }]>; +} + +export declare const MAT_RADIO_DEFAULT_OPTIONS: InjectionToken; + +export declare function MAT_RADIO_DEFAULT_OPTIONS_FACTORY(): MatRadioDefaultOptions; + +export declare const MAT_RADIO_GROUP_CONTROL_VALUE_ACCESSOR: any; + +export declare class MatRadioButton extends _MatRadioButtonBase { + static ɵcmp: i0.ɵɵComponentDefWithMeta; + static ɵfac: i0.ɵɵFactoryDef; } export declare class MatRadioChange {