Skip to content

Commit

Permalink
feat(modal): add 'aria-describedby' for modal window (#3695)
Browse files Browse the repository at this point in the history
Fixes #3678
  • Loading branch information
gpolychronis committed Apr 22, 2020
1 parent 1d4e30a commit 9a8e70d
Show file tree
Hide file tree
Showing 5 changed files with 25 additions and 1 deletion.
1 change: 1 addition & 0 deletions src/modal/modal-config.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ describe('NgbModalConfig', () => {
it('should have sensible default values', inject([NgbModalConfig], (config: NgbModalConfig) => {

expect(config.ariaLabelledBy).toBeUndefined();
expect(config.ariaDescribedBy).toBeUndefined();
expect(config.backdrop).toBe(true);
expect(config.backdropClass).toBeUndefined();
expect(config.beforeDismiss).toBeUndefined();
Expand Down
7 changes: 7 additions & 0 deletions src/modal/modal-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ export interface NgbModalOptions {
*/
ariaLabelledBy?: string;

/**
* `aria-describedby` attribute value to set on the modal window.
*/
ariaDescribedBy?: string;


/**
* If `true`, the backdrop element will be created for a given modal.
*
Expand Down Expand Up @@ -97,6 +103,7 @@ export interface NgbModalOptions {
@Injectable({providedIn: 'root'})
export class NgbModalConfig implements Required<NgbModalOptions> {
ariaLabelledBy: string;
ariaDescribedBy: string;
backdrop: boolean | 'static' = true;
beforeDismiss: () => boolean | Promise<boolean>;
centered: boolean;
Expand Down
2 changes: 1 addition & 1 deletion src/modal/modal-stack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export class NgbModalStack {
private _backdropAttributes = ['backdropClass'];
private _modalRefs: NgbModalRef[] = [];
private _windowAttributes =
['ariaLabelledBy', 'backdrop', 'centered', 'keyboard', 'scrollable', 'size', 'windowClass'];
['ariaLabelledBy', 'ariaDescribedBy', 'backdrop', 'centered', 'keyboard', 'scrollable', 'size', 'windowClass'];
private _windowCmpts: ComponentRef<NgbModalWindow>[] = [];

constructor(
Expand Down
2 changes: 2 additions & 0 deletions src/modal/modal-window.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {ModalDismissReasons} from './modal-dismiss-reasons';
'tabindex': '-1',
'[attr.aria-modal]': 'true',
'[attr.aria-labelledby]': 'ariaLabelledBy',
'[attr.aria-describedby]': 'ariaDescribedBy',
},
template: `
<div #dialog [class]="'modal-dialog' + (size ? ' modal-' + size : '') + (centered ? ' modal-dialog-centered' : '') +
Expand All @@ -46,6 +47,7 @@ export class NgbModalWindow implements OnInit,
@ViewChild('dialog', {static: true}) private _dialogEl: ElementRef<HTMLElement>;

@Input() ariaLabelledBy: string;
@Input() ariaDescribedBy: string;
@Input() backdrop: boolean | string = true;
@Input() centered: string;
@Input() keyboard = true;
Expand Down
14 changes: 14 additions & 0 deletions src/modal/modal.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -669,6 +669,20 @@ describe('ngb-modal', () => {
expect(fixture.nativeElement).not.toHaveModal();
});

it('should support aria-describedby', () => {
const id = 'aria-describedby-id';

const modalInstance = fixture.componentInstance.open('foo', {ariaDescribedBy: id});
fixture.detectChanges();

const modalElement = <HTMLElement>document.querySelector('ngb-modal-window');
expect(modalElement.getAttribute('aria-describedby')).toBe(id);

modalInstance.close('some result');
fixture.detectChanges();
expect(fixture.nativeElement).not.toHaveModal();
});

it('should have aria-modal attribute', () => {
const a11yFixture = TestBed.createComponent(TestA11yComponent);
const modalInstance = a11yFixture.componentInstance.open();
Expand Down

0 comments on commit 9a8e70d

Please sign in to comment.