Skip to content

Commit 7d0bca7

Browse files
authored
feat(cdk/a11y): add input to control the duration of the aria live directive (#15275)
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 09a906a commit 7d0bca7

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)