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 {