Skip to content

Commit 4557d58

Browse files
crisbetojelbourn
authored andcommitted
fix(material-experimental/mdc-radio): avoid bundling styles from base radio button (#19032)
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. (cherry picked from commit 506b74a)
1 parent fd0217d commit 4557d58

File tree

3 files changed

+59
-47
lines changed

3 files changed

+59
-47
lines changed

src/material-experimental/mdc-radio/radio.ts

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import {
2424
import {MDCRadioAdapter, MDCRadioFoundation} from '@material/radio';
2525
import {
2626
MAT_RADIO_DEFAULT_OPTIONS,
27-
MatRadioButton as BaseMatRadioButton,
27+
_MatRadioButtonBase,
2828
MatRadioDefaultOptions,
2929
MatRadioGroup as BaseMatRadioGroup,
3030
} from '@angular/material/radio';
@@ -71,8 +71,8 @@ const RIPPLE_ANIMATION_CONFIG: RippleAnimationConfig = {
7171
})
7272
export class MatRadioGroup extends BaseMatRadioGroup {
7373
/** Child radio buttons. */
74-
@ContentChildren(forwardRef(() => MatRadioButton), { descendants: true })
75-
_radios: QueryList<BaseMatRadioButton>;
74+
@ContentChildren(forwardRef(() => MatRadioButton), {descendants: true})
75+
_radios: QueryList<_MatRadioButtonBase>;
7676
}
7777

7878
@Component({
@@ -81,9 +81,6 @@ export class MatRadioGroup extends BaseMatRadioGroup {
8181
styleUrls: ['radio.css'],
8282
host: {
8383
'class': 'mat-mdc-radio-button',
84-
// Ivy will inherit the mat-radio-button class from the parent class, but we do not want
85-
// this to be applied in the MDC component. Set this explicitly to false so it is not applied.
86-
'[class.mat-radio-button]': 'false',
8784
'[attr.id]': 'id',
8885
'[class.mat-primary]': 'color === "primary"',
8986
'[class.mat-accent]': 'color === "accent"',
@@ -102,7 +99,7 @@ export class MatRadioGroup extends BaseMatRadioGroup {
10299
encapsulation: ViewEncapsulation.None,
103100
changeDetection: ChangeDetectionStrategy.OnPush,
104101
})
105-
export class MatRadioButton extends BaseMatRadioButton implements AfterViewInit, OnDestroy {
102+
export class MatRadioButton extends _MatRadioButtonBase implements AfterViewInit, OnDestroy {
106103

107104
private _radioAdapter: MDCRadioAdapter = {
108105
addClass: (className: string) => this._setClass(className, true),

src/material/radio/radio.ts

Lines changed: 41 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -328,38 +328,13 @@ const _MatRadioButtonMixinBase:
328328
mixinDisableRipple(mixinTabIndex(MatRadioButtonBase));
329329

330330
/**
331-
* A Material design radio-button. Typically placed inside of `<mat-radio-group>` elements.
331+
* Base class with all of the `MatRadioButton` functionality.
332+
* @docs-private
332333
*/
333-
@Component({
334-
selector: 'mat-radio-button',
335-
templateUrl: 'radio.html',
336-
styleUrls: ['radio.css'],
337-
inputs: ['disableRipple', 'tabIndex'],
338-
encapsulation: ViewEncapsulation.None,
339-
exportAs: 'matRadioButton',
340-
host: {
341-
'class': 'mat-radio-button',
342-
'[class.mat-radio-checked]': 'checked',
343-
'[class.mat-radio-disabled]': 'disabled',
344-
'[class._mat-animation-noopable]': '_animationMode === "NoopAnimations"',
345-
'[class.mat-primary]': 'color === "primary"',
346-
'[class.mat-accent]': 'color === "accent"',
347-
'[class.mat-warn]': 'color === "warn"',
348-
// Needs to be -1 so the `focus` event still fires.
349-
'[attr.tabindex]': '-1',
350-
'[attr.id]': 'id',
351-
'[attr.aria-label]': 'null',
352-
'[attr.aria-labelledby]': 'null',
353-
'[attr.aria-describedby]': 'null',
354-
// Note: under normal conditions focus shouldn't land on this element, however it may be
355-
// programmatically set, for example inside of a focus trap, in this case we want to forward
356-
// the focus to the native element.
357-
'(focus)': '_inputElement.nativeElement.focus()',
358-
},
359-
changeDetection: ChangeDetectionStrategy.OnPush,
360-
})
361-
export class MatRadioButton extends _MatRadioButtonMixinBase
362-
implements OnInit, AfterViewInit, OnDestroy, CanDisableRipple, HasTabIndex {
334+
@Directive()
335+
// tslint:disable-next-line:class-name
336+
export abstract class _MatRadioButtonBase extends _MatRadioButtonMixinBase implements OnInit,
337+
AfterViewInit, OnDestroy, CanDisableRipple, HasTabIndex {
363338

364339
private _uniqueId: string = `mat-radio-${++nextUniqueId}`;
365340

@@ -606,3 +581,38 @@ export class MatRadioButton extends _MatRadioButtonMixinBase
606581
static ngAcceptInputType_required: BooleanInput;
607582
static ngAcceptInputType_disableRipple: BooleanInput;
608583
}
584+
585+
586+
/**
587+
* A Material design radio-button. Typically placed inside of `<mat-radio-group>` elements.
588+
*/
589+
@Component({
590+
selector: 'mat-radio-button',
591+
templateUrl: 'radio.html',
592+
styleUrls: ['radio.css'],
593+
inputs: ['disableRipple', 'tabIndex'],
594+
encapsulation: ViewEncapsulation.None,
595+
exportAs: 'matRadioButton',
596+
host: {
597+
'class': 'mat-radio-button',
598+
'[class.mat-radio-checked]': 'checked',
599+
'[class.mat-radio-disabled]': 'disabled',
600+
'[class._mat-animation-noopable]': '_animationMode === "NoopAnimations"',
601+
'[class.mat-primary]': 'color === "primary"',
602+
'[class.mat-accent]': 'color === "accent"',
603+
'[class.mat-warn]': 'color === "warn"',
604+
// Needs to be -1 so the `focus` event still fires.
605+
'[attr.tabindex]': '-1',
606+
'[attr.id]': 'id',
607+
'[attr.aria-label]': 'null',
608+
'[attr.aria-labelledby]': 'null',
609+
'[attr.aria-describedby]': 'null',
610+
// Note: under normal conditions focus shouldn't land on this element, however it may be
611+
// programmatically set, for example inside of a focus trap, in this case we want to forward
612+
// the focus to the native element.
613+
'(focus)': '_inputElement.nativeElement.focus()',
614+
},
615+
changeDetection: ChangeDetectionStrategy.OnPush,
616+
})
617+
export class MatRadioButton extends _MatRadioButtonBase {
618+
}

tools/public_api_guard/material/radio.d.ts

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,4 @@
1-
export declare const MAT_RADIO_DEFAULT_OPTIONS: InjectionToken<MatRadioDefaultOptions>;
2-
3-
export declare function MAT_RADIO_DEFAULT_OPTIONS_FACTORY(): MatRadioDefaultOptions;
4-
5-
export declare const MAT_RADIO_GROUP_CONTROL_VALUE_ACCESSOR: any;
6-
7-
export declare class MatRadioButton extends _MatRadioButtonMixinBase implements OnInit, AfterViewInit, OnDestroy, CanDisableRipple, HasTabIndex {
1+
export declare abstract class _MatRadioButtonBase extends _MatRadioButtonMixinBase implements OnInit, AfterViewInit, OnDestroy, CanDisableRipple, HasTabIndex {
82
_animationMode?: string | undefined;
93
protected _changeDetector: ChangeDetectorRef;
104
_inputElement: ElementRef<HTMLInputElement>;
@@ -42,8 +36,19 @@ export declare class MatRadioButton extends _MatRadioButtonMixinBase implements
4236
static ngAcceptInputType_disableRipple: BooleanInput;
4337
static ngAcceptInputType_disabled: BooleanInput;
4438
static ngAcceptInputType_required: BooleanInput;
45-
static ɵcmp: i0.ɵɵComponentDefWithMeta<MatRadioButton, "mat-radio-button", ["matRadioButton"], { "disableRipple": "disableRipple"; "tabIndex": "tabIndex"; "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, ["*"]>;
46-
static ɵfac: i0.ɵɵFactoryDef<MatRadioButton, [{ optional: true; }, null, null, null, null, { optional: true; }, { optional: true; }]>;
39+
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>;
40+
static ɵfac: i0.ɵɵFactoryDef<_MatRadioButtonBase, [{ optional: true; }, null, null, null, null, { optional: true; }, { optional: true; }]>;
41+
}
42+
43+
export declare const MAT_RADIO_DEFAULT_OPTIONS: InjectionToken<MatRadioDefaultOptions>;
44+
45+
export declare function MAT_RADIO_DEFAULT_OPTIONS_FACTORY(): MatRadioDefaultOptions;
46+
47+
export declare const MAT_RADIO_GROUP_CONTROL_VALUE_ACCESSOR: any;
48+
49+
export declare class MatRadioButton extends _MatRadioButtonBase {
50+
static ɵcmp: i0.ɵɵComponentDefWithMeta<MatRadioButton, "mat-radio-button", ["matRadioButton"], { "disableRipple": "disableRipple"; "tabIndex": "tabIndex"; }, {}, never, ["*"]>;
51+
static ɵfac: i0.ɵɵFactoryDef<MatRadioButton, never>;
4752
}
4853

4954
export declare class MatRadioChange {

0 commit comments

Comments
 (0)