From 15b3a8660c02ce5f52210742aac9fbacf64dac7a Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Sun, 4 Jan 2026 09:53:11 +0100 Subject: [PATCH] fix(material/radio): allow aria attributes to be reset Fixes that it wasn't possible to reset the aria-* attributes for the radio button. Fixes #31790. --- goldens/material/radio/index.api.md | 6 +++--- src/material/radio/radio.spec.ts | 24 ++++++++++++++++++------ src/material/radio/radio.ts | 6 +++--- 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/goldens/material/radio/index.api.md b/goldens/material/radio/index.api.md index 77d240a65330..2b741095c53f 100644 --- a/goldens/material/radio/index.api.md +++ b/goldens/material/radio/index.api.md @@ -30,9 +30,9 @@ export const MAT_RADIO_GROUP_CONTROL_VALUE_ACCESSOR: any; // @public (undocumented) export class MatRadioButton implements OnInit, AfterViewInit, DoCheck, OnDestroy { constructor(...args: unknown[]); - ariaDescribedby: string; - ariaLabel: string; - ariaLabelledby: string; + ariaDescribedby: string | null; + ariaLabel: string | null; + ariaLabelledby: string | null; readonly change: EventEmitter; get checked(): boolean; set checked(value: boolean); diff --git a/src/material/radio/radio.spec.ts b/src/material/radio/radio.spec.ts index 8c03a5e50147..63e346109a70 100644 --- a/src/material/radio/radio.spec.ts +++ b/src/material/radio/radio.spec.ts @@ -816,8 +816,12 @@ describe('MatRadio', () => { testComponent.ariaLabel = 'Pineapple'; fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); - expect(fruitRadioNativeInputs[0].getAttribute('aria-label')).toBe('Pineapple'); + + testComponent.ariaLabel = null; + fixture.changeDetectorRef.markForCheck(); + fixture.detectChanges(); + expect(fruitRadioNativeInputs[0].hasAttribute('aria-label')).toBe(false); }); it('should add aria-labelledby attribute to the underlying input element if defined', () => { @@ -834,8 +838,12 @@ describe('MatRadio', () => { testComponent.ariaLabelledby = 'uvw'; fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); - expect(fruitRadioNativeInputs[0].getAttribute('aria-labelledby')).toBe('uvw'); + + testComponent.ariaLabelledby = null; + fixture.changeDetectorRef.markForCheck(); + fixture.detectChanges(); + expect(fruitRadioNativeInputs[0].hasAttribute('aria-labelledby')).toBe(false); }); it('should add aria-describedby attribute to the underlying input element if defined', () => { @@ -852,8 +860,12 @@ describe('MatRadio', () => { testComponent.ariaDescribedby = 'uvw'; fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); - expect(fruitRadioNativeInputs[0].getAttribute('aria-describedby')).toBe('uvw'); + + testComponent.ariaDescribedby = null; + fixture.changeDetectorRef.markForCheck(); + fixture.detectChanges(); + expect(fruitRadioNativeInputs[0].hasAttribute('aria-describedby')).toBe(false); }); it('should focus on underlying input element when focus() is called', () => { @@ -1117,9 +1129,9 @@ class RadiosInsidePreCheckedRadioGroup {} imports: [MatRadioModule, FormsModule, ReactiveFormsModule], }) class StandaloneRadioButtons { - ariaLabel: string = 'Banana'; - ariaLabelledby: string = 'xyz'; - ariaDescribedby: string = 'abc'; + ariaLabel: string | null = 'Banana'; + ariaLabelledby: string | null = 'xyz'; + ariaDescribedby: string | null = 'abc'; } @Component({ diff --git a/src/material/radio/radio.ts b/src/material/radio/radio.ts index b44a647c1ce3..0e142fc33718 100644 --- a/src/material/radio/radio.ts +++ b/src/material/radio/radio.ts @@ -427,13 +427,13 @@ export class MatRadioButton implements OnInit, AfterViewInit, DoCheck, OnDestroy @Input() name!: string; /** Used to set the 'aria-label' attribute on the underlying input element. */ - @Input('aria-label') ariaLabel!: string; + @Input('aria-label') ariaLabel!: string | null; /** The 'aria-labelledby' attribute takes precedence as the element's text alternative. */ - @Input('aria-labelledby') ariaLabelledby!: string; + @Input('aria-labelledby') ariaLabelledby!: string | null; /** The 'aria-describedby' attribute is read after the element's label and field type. */ - @Input('aria-describedby') ariaDescribedby!: string; + @Input('aria-describedby') ariaDescribedby!: string | null; /** Whether ripples are disabled inside the radio button */ @Input({transform: booleanAttribute})