diff --git a/src/material/chips/chip-grid.ts b/src/material/chips/chip-grid.ts index 9e0132d0e5d2..f670ec6f859c 100644 --- a/src/material/chips/chip-grid.ts +++ b/src/material/chips/chip-grid.ts @@ -106,6 +106,11 @@ export class MatChipGrid */ private _ariaDescribedbyIds: string[] = []; + /** + * List of element ids to propagate to the chipInput's aria-labelledby attribute. + */ + private _ariaLabelledbyIds: string[] = []; + /** * Function when touched. Set as part of ControlValueAccessor implementation. * @docs-private @@ -311,6 +316,7 @@ export class MatChipGrid registerInput(inputElement: MatChipTextControl): void { this._chipInput = inputElement; this._chipInput.setDescribedByIds(this._ariaDescribedbyIds); + this._chipInput.setLabelledByIds(this._ariaLabelledbyIds); } /** @@ -360,6 +366,13 @@ export class MatChipGrid this._chipInput?.setDescribedByIds(ids); } + setLabelledByIds(ids: string[]) { + // We must keep this up to date to handle the case where ids are set + // before the chip input is registered. + this._ariaDescribedbyIds = ids; + this._chipInput?.setLabelledByIds(ids); + } + /** * Implemented as part of ControlValueAccessor. * @docs-private diff --git a/src/material/chips/chip-input.ts b/src/material/chips/chip-input.ts index 6c6c68be4063..499762ba569a 100644 --- a/src/material/chips/chip-input.ts +++ b/src/material/chips/chip-input.ts @@ -219,6 +219,18 @@ export class MatChipInput implements MatChipTextControl, OnChanges, OnDestroy { } } + setLabelledByIds(ids: string[]): void { + const element = this._elementRef.nativeElement; + + // Set the value directly in the DOM since this binding + // is prone to "changed after checked" errors. + if (ids.length) { + element.setAttribute('aria-labelledby', ids.join(' ')); + } else { + element.removeAttribute('aria-labelledby'); + } + } + /** Checks whether a keycode is one of the configured separators. */ private _isSeparatorKey(event: KeyboardEvent) { return !hasModifierKey(event) && new Set(this.separatorKeyCodes).has(event.keyCode); diff --git a/src/material/chips/chip-text-control.ts b/src/material/chips/chip-text-control.ts index 5cc80f363ddd..3798e04f6e9a 100644 --- a/src/material/chips/chip-text-control.ts +++ b/src/material/chips/chip-text-control.ts @@ -25,4 +25,7 @@ export interface MatChipTextControl { /** Sets the list of ids the input is described by. */ setDescribedByIds(ids: string[]): void; + + /** Sets the list of ids the input is labelled by. */ + setLabelledByIds(ids: string[]): void; } diff --git a/src/material/form-field/form-field-control.ts b/src/material/form-field/form-field-control.ts index c828280f5565..95cc0e97f3f2 100644 --- a/src/material/form-field/form-field-control.ts +++ b/src/material/form-field/form-field-control.ts @@ -68,6 +68,12 @@ export abstract class MatFormFieldControl { */ readonly userAriaDescribedBy?: string; + /** + * Value of `aria-labelledby` that should be merged with the labelled-by ids + * which are set by the form-field. + */ + readonly userAriaLabelledBy?: string; + /** * Whether to automatically assign the ID of the form field as the `for` attribute * on the `