From 3e935e9b79108e517d41cd10b2613afef8fbffba Mon Sep 17 00:00:00 2001 From: John Crowson Date: Tue, 5 Feb 2019 10:32:54 -0500 Subject: [PATCH] feat(dialog): add ariaLabelledBy config option (#14943) Adds the ability to set the `aria-labelledby` of a dialog without mat-dialog-title. --- src/lib/dialog/dialog-config.ts | 3 ++ src/lib/dialog/dialog-container.ts | 3 +- src/lib/dialog/dialog.spec.ts | 45 ++++++++++++++++++++++++++ tools/public_api_guard/lib/dialog.d.ts | 1 + 4 files changed, 51 insertions(+), 1 deletion(-) diff --git a/src/lib/dialog/dialog-config.ts b/src/lib/dialog/dialog-config.ts index add3efbe906..b99863d1ebb 100644 --- a/src/lib/dialog/dialog-config.ts +++ b/src/lib/dialog/dialog-config.ts @@ -89,6 +89,9 @@ export class MatDialogConfig { /** ID of the element that describes the dialog. */ ariaDescribedBy?: string | null = null; + /** ID of the element that labels the dialog. */ + ariaLabelledBy?: string | null = null; + /** Aria label to assign to the dialog element */ ariaLabel?: string | null = null; diff --git a/src/lib/dialog/dialog-container.ts b/src/lib/dialog/dialog-container.ts index fbcbacc6c8d..0a22e9b9c30 100644 --- a/src/lib/dialog/dialog-container.ts +++ b/src/lib/dialog/dialog-container.ts @@ -87,7 +87,7 @@ export class MatDialogContainer extends BasePortalOutlet { _animationStateChanged = new EventEmitter(); /** ID of the element that should be considered as the dialog's label. */ - _ariaLabelledBy: string | null = null; + _ariaLabelledBy: string | null; /** ID for the container DOM element. */ _id: string; @@ -101,6 +101,7 @@ export class MatDialogContainer extends BasePortalOutlet { public _config: MatDialogConfig) { super(); + this._ariaLabelledBy = _config.ariaLabelledBy || null; } /** diff --git a/src/lib/dialog/dialog.spec.ts b/src/lib/dialog/dialog.spec.ts index 1195958d9ff..b2746d5079a 100644 --- a/src/lib/dialog/dialog.spec.ts +++ b/src/lib/dialog/dialog.spec.ts @@ -1180,6 +1180,51 @@ describe('MatDialog', () => { } }); + describe('aria-labelledby', () => { + it('should be able to set a custom aria-labelledby', () => { + dialog.open(PizzaMsg, { + ariaLabelledBy: 'Labelled By', + viewContainerRef: testViewContainerRef + }); + viewContainerFixture.detectChanges(); + + const container = overlayContainerElement.querySelector('mat-dialog-container')!; + expect(container.getAttribute('aria-labelledby')).toBe('Labelled By'); + }); + + it('should not set the aria-labelledby automatically if it has an aria-label ' + + 'and an aria-labelledby', fakeAsync(() => { + dialog.open(ContentElementDialog, { + ariaLabel: 'Hello there', + ariaLabelledBy: 'Labelled By', + viewContainerRef: testViewContainerRef + }); + viewContainerFixture.detectChanges(); + tick(); + viewContainerFixture.detectChanges(); + + const container = overlayContainerElement.querySelector('mat-dialog-container')!; + expect(container.hasAttribute('aria-labelledby')).toBe(false); + })); + + it('should set the aria-labelledby attribute to the config provided aria-labelledby ' + + 'instead of the mat-dialog-title id', fakeAsync(() => { + dialog.open(ContentElementDialog, { + ariaLabelledBy: 'Labelled By', + viewContainerRef: testViewContainerRef + }); + viewContainerFixture.detectChanges(); + flush(); + let title = overlayContainerElement.querySelector('[mat-dialog-title]')!; + let container = overlayContainerElement.querySelector('mat-dialog-container')!; + flush(); + viewContainerFixture.detectChanges(); + + expect(title.id).toBeTruthy('Expected title element to have an id.'); + expect(container.getAttribute('aria-labelledby')).toBe('Labelled By'); + })); + }); + describe('aria-label', () => { it('should be able to set a custom aria-label', () => { dialog.open(PizzaMsg, { diff --git a/tools/public_api_guard/lib/dialog.d.ts b/tools/public_api_guard/lib/dialog.d.ts index 36cb08056b9..dfdf6145045 100644 --- a/tools/public_api_guard/lib/dialog.d.ts +++ b/tools/public_api_guard/lib/dialog.d.ts @@ -57,6 +57,7 @@ export declare class MatDialogClose implements OnInit, OnChanges { export declare class MatDialogConfig { ariaDescribedBy?: string | null; ariaLabel?: string | null; + ariaLabelledBy?: string | null; autoFocus?: boolean; backdropClass?: string; closeOnNavigation?: boolean;