Skip to content

Commit 2a11276

Browse files
committed
feat(cdk/a11y): add input to control the duration of the aria live directive
Adds an input that allows the consumer to control how long it takes before the messages that are announced by `CdkAriaLive` to be cleared from the DOM.
1 parent 0dfc490 commit 2a11276

File tree

3 files changed

+30
-10
lines changed

3 files changed

+30
-10
lines changed

src/cdk/a11y/live-announcer/live-announcer.spec.ts

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import {MutationObserverFactory} from '@angular/cdk/observers';
2-
import {Component, Input} from '@angular/core';
2+
import {Component} from '@angular/core';
33
import {ComponentFixture, fakeAsync, flush, inject, TestBed, tick} from '@angular/core/testing';
44
import {By} from '@angular/platform-browser';
5-
import {A11yModule, AriaLivePoliteness} from '../index';
5+
import {A11yModule} from '../index';
66
import {LiveAnnouncer} from './live-announcer';
77
import {
88
LIVE_ANNOUNCER_ELEMENT_TOKEN,
@@ -280,7 +280,7 @@ describe('CdkAriaLive', () => {
280280
invokeMutationCallbacks();
281281
flush();
282282

283-
expect(announcer.announce).toHaveBeenCalledWith('New content', 'polite');
283+
expect(announcer.announce).toHaveBeenCalledWith('New content', 'polite', undefined);
284284
}));
285285

286286
it('should dynamically update the politeness', fakeAsync(() => {
@@ -289,7 +289,7 @@ describe('CdkAriaLive', () => {
289289
invokeMutationCallbacks();
290290
flush();
291291

292-
expect(announcer.announce).toHaveBeenCalledWith('New content', 'polite');
292+
expect(announcer.announce).toHaveBeenCalledWith('New content', 'polite', undefined);
293293

294294
announcerSpy.calls.reset();
295295
fixture.componentInstance.politeness = 'off';
@@ -307,7 +307,7 @@ describe('CdkAriaLive', () => {
307307
invokeMutationCallbacks();
308308
flush();
309309

310-
expect(announcer.announce).toHaveBeenCalledWith('Newest content', 'assertive');
310+
expect(announcer.announce).toHaveBeenCalledWith('Newest content', 'assertive', undefined);
311311
}));
312312

313313
it('should not announce the same text multiple times', fakeAsync(() => {
@@ -324,6 +324,16 @@ describe('CdkAriaLive', () => {
324324

325325
expect(announcer.announce).toHaveBeenCalledTimes(1);
326326
}));
327+
328+
it('should be able to pass in a duration', fakeAsync(() => {
329+
fixture.componentInstance.content = 'New content';
330+
fixture.componentInstance.duration = 1337;
331+
fixture.detectChanges();
332+
invokeMutationCallbacks();
333+
flush();
334+
335+
expect(announcer.announce).toHaveBeenCalledWith('New content', 'polite', 1337);
336+
}));
327337
});
328338

329339
function getLiveElement(): Element {
@@ -339,8 +349,14 @@ class TestApp {
339349
}
340350
}
341351

342-
@Component({template: `<div [cdkAriaLive]="politeness ? politeness : null">{{content}}</div>`})
352+
@Component({
353+
template: `
354+
<div
355+
[cdkAriaLive]="politeness ? politeness : null"
356+
[cdkAriaLiveDuration]="duration">{{content}}</div>`,
357+
})
343358
class DivWithCdkAriaLive {
344-
@Input() politeness: AriaLivePoliteness;
345-
@Input() content = 'Initial content';
359+
politeness = 'polite';
360+
content = 'Initial content';
361+
duration: number;
346362
}

src/cdk/a11y/live-announcer/live-announcer.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ export class CdkAriaLive implements OnDestroy {
198198
// The `MutationObserver` fires also for attribute
199199
// changes which we don't want to announce.
200200
if (elementText !== this._previousAnnouncedText) {
201-
this._liveAnnouncer.announce(elementText, this._politeness);
201+
this._liveAnnouncer.announce(elementText, this._politeness, this.duration);
202202
this._previousAnnouncedText = elementText;
203203
}
204204
});
@@ -207,6 +207,9 @@ export class CdkAriaLive implements OnDestroy {
207207
}
208208
private _politeness: AriaLivePoliteness = 'polite';
209209

210+
/** Time in milliseconds after which to clear out the announcer element. */
211+
@Input('cdkAriaLiveDuration') duration: number;
212+
210213
private _previousAnnouncedText?: string;
211214
private _subscription: Subscription | null;
212215

tools/public_api_guard/cdk/a11y.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,12 +67,13 @@ export const CDK_DESCRIBEDBY_ID_PREFIX = "cdk-describedby-message";
6767
// @public
6868
export class CdkAriaLive implements OnDestroy {
6969
constructor(_elementRef: ElementRef, _liveAnnouncer: LiveAnnouncer, _contentObserver: ContentObserver, _ngZone: NgZone);
70+
duration: number;
7071
// (undocumented)
7172
ngOnDestroy(): void;
7273
get politeness(): AriaLivePoliteness;
7374
set politeness(value: AriaLivePoliteness);
7475
// (undocumented)
75-
static ɵdir: i0.ɵɵDirectiveDeclaration<CdkAriaLive, "[cdkAriaLive]", ["cdkAriaLive"], { "politeness": "cdkAriaLive"; }, {}, never>;
76+
static ɵdir: i0.ɵɵDirectiveDeclaration<CdkAriaLive, "[cdkAriaLive]", ["cdkAriaLive"], { "politeness": "cdkAriaLive"; "duration": "cdkAriaLiveDuration"; }, {}, never>;
7677
// (undocumented)
7778
static ɵfac: i0.ɵɵFactoryDeclaration<CdkAriaLive, never>;
7879
}

0 commit comments

Comments
 (0)