Skip to content

Commit 44cbb82

Browse files
committed
fix(dialog): set aria-describedby based on content element
Sets the `aria-describedby` attribute on the dialog based on the `md-dialog-content`. This allows for screen readers to pick up and read out the dialog contents.
1 parent 38b365c commit 44cbb82

File tree

3 files changed

+31
-3
lines changed

3 files changed

+31
-3
lines changed

src/lib/dialog/dialog-container.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ export function throwMdDialogContentAlreadyAttachedError() {
6767
'class': 'mat-dialog-container',
6868
'[attr.role]': '_config?.role',
6969
'[attr.aria-labelledby]': '_ariaLabelledBy',
70+
'[attr.aria-describedby]': '_ariaDescribedBy',
7071
'[@slideDialog]': '_state',
7172
'(@slideDialog.done)': '_onAnimationDone($event)',
7273
},
@@ -96,6 +97,9 @@ export class MdDialogContainer extends BasePortalHost {
9697
/** ID of the element that should be considered as the dialog's label. */
9798
_ariaLabelledBy: string | null = null;
9899

100+
/** ID of the element that should be considered as the dialog's content. */
101+
_ariaDescribedBy: string | null = null;
102+
99103
constructor(
100104
private _ngZone: NgZone,
101105
private _elementRef: ElementRef,

src/lib/dialog/dialog-content-directives.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,22 @@ export class MdDialogTitle implements OnInit {
6767
@Directive({
6868
selector: '[md-dialog-content], md-dialog-content, [mat-dialog-content], mat-dialog-content,' +
6969
'[mdDialogContent], [matDialogContent]',
70-
host: {'class': 'mat-dialog-content'}
70+
host: {
71+
'class': 'mat-dialog-content',
72+
'[id]': 'id'
73+
}
7174
})
72-
export class MdDialogContent { }
75+
export class MdDialogContent implements OnInit {
76+
@Input() id = `md-dialog-content-${dialogElementUid++}`;
77+
78+
constructor(@Optional() private _container: MdDialogContainer) { }
79+
80+
ngOnInit() {
81+
if (this._container && !this._container._ariaDescribedBy) {
82+
Promise.resolve().then(() => this._container._ariaDescribedBy = this.id);
83+
}
84+
}
85+
}
7386

7487

7588
/**

src/lib/dialog/dialog.spec.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -666,7 +666,7 @@ describe('MdDialog', () => {
666666
});
667667
}));
668668

669-
it('should set the aria-labelled by attribute to the id of the title', async(() => {
669+
it('should set the aria-labelledby attribute to the id of the title', async(() => {
670670
let title = overlayContainerElement.querySelector('[md-dialog-title]')!;
671671
let container = overlayContainerElement.querySelector('md-dialog-container')!;
672672

@@ -677,6 +677,17 @@ describe('MdDialog', () => {
677677
});
678678
}));
679679

680+
it('should set the aria-describedby attribute to the id of the content', async(() => {
681+
let content = overlayContainerElement.querySelector('md-dialog-content')!;
682+
let container = overlayContainerElement.querySelector('md-dialog-container')!;
683+
684+
viewContainerFixture.whenStable().then(() => {
685+
expect(content.id).toBeTruthy('Expected content element to have an id.');
686+
expect(container.getAttribute('aria-describedby'))
687+
.toBe(content.id, 'Expected the aria-describedby to match the title id.');
688+
});
689+
}));
690+
680691
});
681692
});
682693

0 commit comments

Comments
 (0)