diff --git a/goldens/size-test.yaml b/goldens/size-test.yaml index 201351912a40..adfbd99cb03d 100644 --- a/goldens/size-test.yaml +++ b/goldens/size-test.yaml @@ -1 +1,2 @@ material/list/nav-list: 130473 +material/radio/without-group: 121448 diff --git a/integration/size-test/material/radio/BUILD.bazel b/integration/size-test/material/radio/BUILD.bazel new file mode 100644 index 000000000000..12e1478d275f --- /dev/null +++ b/integration/size-test/material/radio/BUILD.bazel @@ -0,0 +1,7 @@ +load("//integration/size-test:index.bzl", "size_test") + +size_test( + name = "without-group", + file = "without-group.ts", + deps = ["//src/material/radio"], +) diff --git a/integration/size-test/material/radio/without-group.ts b/integration/size-test/material/radio/without-group.ts new file mode 100644 index 000000000000..fb1e148f002c --- /dev/null +++ b/integration/size-test/material/radio/without-group.ts @@ -0,0 +1,23 @@ +import {Component, NgModule} from '@angular/core'; +import {MatRadioModule} from '@angular/material/radio'; +import {platformBrowser} from '@angular/platform-browser'; + +/** + * Basic component using `MatRadioButton`. Doesn't use a `MatRadioGroup`, so the class + * should be tree-shaken away properly. + */ +@Component({ + template: ` + + `, +}) +export class TestComponent {} + +@NgModule({ + imports: [MatRadioModule], + declarations: [TestComponent], + bootstrap: [TestComponent], +}) +export class AppModule {} + +platformBrowser().bootstrapModule(AppModule); diff --git a/src/material-experimental/mdc-radio/radio.ts b/src/material-experimental/mdc-radio/radio.ts index 9857e4fc18bb..9ddc9986979b 100644 --- a/src/material-experimental/mdc-radio/radio.ts +++ b/src/material-experimental/mdc-radio/radio.ts @@ -16,6 +16,7 @@ import { ElementRef, forwardRef, Inject, + InjectionToken, OnDestroy, Optional, QueryList, @@ -50,6 +51,14 @@ export const MAT_RADIO_GROUP_CONTROL_VALUE_ACCESSOR: any = { multi: true }; +/** + * Injection token that can be used to inject instances of `MatRadioGroup`. It serves as + * alternative token to the actual `MatRadioGroup` class which could cause unnecessary + * retention of the class and its component metadata. + */ +export const MAT_RADIO_GROUP = + new InjectionToken<_MatRadioGroupBase<_MatRadioButtonBase>>('MatRadioGroup'); + /** Configuration for the ripple animation. */ const RIPPLE_ANIMATION_CONFIG: RippleAnimationConfig = { enterDuration: numbers.DEACTIVATION_TIMEOUT_MS, @@ -62,7 +71,10 @@ const RIPPLE_ANIMATION_CONFIG: RippleAnimationConfig = { @Directive({ selector: 'mat-radio-group', exportAs: 'matRadioGroup', - providers: [MAT_RADIO_GROUP_CONTROL_VALUE_ACCESSOR], + providers: [ + MAT_RADIO_GROUP_CONTROL_VALUE_ACCESSOR, + {provide: MAT_RADIO_GROUP, useExisting: MatRadioGroup}, + ], host: { 'role': 'radiogroup', 'class': 'mat-mdc-radio-group', @@ -117,7 +129,7 @@ export class MatRadioButton extends _MatRadioButtonBase implements AfterViewInit _radioFoundation = new MDCRadioFoundation(this._radioAdapter); _classes: {[key: string]: boolean} = {}; - constructor(@Optional() radioGroup: MatRadioGroup, + constructor(@Optional() @Inject(MAT_RADIO_GROUP) radioGroup: MatRadioGroup, elementRef: ElementRef, _changeDetector: ChangeDetectorRef, _focusMonitor: FocusMonitor, diff --git a/src/material/radio/radio.ts b/src/material/radio/radio.ts index 588bb310b273..6944c5d93529 100644 --- a/src/material/radio/radio.ts +++ b/src/material/radio/radio.ts @@ -83,6 +83,14 @@ export class MatRadioChange { public value: any) {} } +/** + * Injection token that can be used to inject instances of `MatRadioGroup`. It serves as + * alternative token to the actual `MatRadioGroup` class which could cause unnecessary + * retention of the class and its component metadata. + */ +export const MAT_RADIO_GROUP = + new InjectionToken<_MatRadioGroupBase<_MatRadioButtonBase>>('MatRadioGroup'); + /** * Base class with all of the `MatRadioGroup` functionality. * @docs-private @@ -311,7 +319,10 @@ export abstract class _MatRadioGroupBase implemen @Directive({ selector: 'mat-radio-group', exportAs: 'matRadioGroup', - providers: [MAT_RADIO_GROUP_CONTROL_VALUE_ACCESSOR], + providers: [ + MAT_RADIO_GROUP_CONTROL_VALUE_ACCESSOR, + {provide: MAT_RADIO_GROUP, useExisting: MatRadioGroup}, + ], host: { 'role': 'radiogroup', 'class': 'mat-radio-group', @@ -475,14 +486,13 @@ export abstract class _MatRadioButtonBase extends _MatRadioButtonMixinBase imple /** The native `` element */ @ViewChild('input') _inputElement: ElementRef; - constructor(@Optional() radioGroup: _MatRadioGroupBase<_MatRadioButtonBase>, + constructor(radioGroup: _MatRadioGroupBase<_MatRadioButtonBase>, elementRef: ElementRef, protected _changeDetector: ChangeDetectorRef, private _focusMonitor: FocusMonitor, private _radioDispatcher: UniqueSelectionDispatcher, - @Optional() @Inject(ANIMATION_MODULE_TYPE) public _animationMode?: string, - @Optional() @Inject(MAT_RADIO_DEFAULT_OPTIONS) - private _providerOverride?: MatRadioDefaultOptions) { + public _animationMode?: string, + private _providerOverride?: MatRadioDefaultOptions) { super(elementRef); // Assertions. Ideally these should be stripped out by the compiler. @@ -626,7 +636,7 @@ export abstract class _MatRadioButtonBase extends _MatRadioButtonMixinBase imple changeDetection: ChangeDetectionStrategy.OnPush, }) export class MatRadioButton extends _MatRadioButtonBase { - constructor(@Optional() radioGroup: MatRadioGroup, + constructor(@Optional() @Inject(MAT_RADIO_GROUP) radioGroup: MatRadioGroup, elementRef: ElementRef, changeDetector: ChangeDetectorRef, focusMonitor: FocusMonitor, diff --git a/tools/public_api_guard/material/radio.d.ts b/tools/public_api_guard/material/radio.d.ts index 1636353cca20..711056836582 100644 --- a/tools/public_api_guard/material/radio.d.ts +++ b/tools/public_api_guard/material/radio.d.ts @@ -37,7 +37,7 @@ export declare abstract class _MatRadioButtonBase extends _MatRadioButtonMixinBa static ngAcceptInputType_disabled: BooleanInput; static ngAcceptInputType_required: BooleanInput; 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; }]>; + static ɵfac: i0.ɵɵFactoryDef<_MatRadioButtonBase, never>; } export declare abstract class _MatRadioGroupBase implements AfterContentInit, ControlValueAccessor { @@ -78,6 +78,8 @@ export declare const MAT_RADIO_DEFAULT_OPTIONS: InjectionToken>; + export declare const MAT_RADIO_GROUP_CONTROL_VALUE_ACCESSOR: any; export declare class MatRadioButton extends _MatRadioButtonBase {