diff --git a/src/cdk/a11y/live-announcer/live-announcer.spec.ts b/src/cdk/a11y/live-announcer/live-announcer.spec.ts index 86b886cdd11f..1ebf44296a41 100644 --- a/src/cdk/a11y/live-announcer/live-announcer.spec.ts +++ b/src/cdk/a11y/live-announcer/live-announcer.spec.ts @@ -1,8 +1,8 @@ import {MutationObserverFactory} from '@angular/cdk/observers'; -import {Component, Input} from '@angular/core'; +import {Component} from '@angular/core'; import {ComponentFixture, fakeAsync, flush, inject, TestBed, tick} from '@angular/core/testing'; import {By} from '@angular/platform-browser'; -import {A11yModule, AriaLivePoliteness} from '../index'; +import {A11yModule} from '../index'; import {LiveAnnouncer} from './live-announcer'; import { LIVE_ANNOUNCER_ELEMENT_TOKEN, @@ -288,7 +288,7 @@ describe('CdkAriaLive', () => { invokeMutationCallbacks(); flush(); - expect(announcer.announce).toHaveBeenCalledWith('New content', 'polite'); + expect(announcer.announce).toHaveBeenCalledWith('New content', 'polite', undefined); })); it('should dynamically update the politeness', fakeAsync(() => { @@ -297,7 +297,7 @@ describe('CdkAriaLive', () => { invokeMutationCallbacks(); flush(); - expect(announcer.announce).toHaveBeenCalledWith('New content', 'polite'); + expect(announcer.announce).toHaveBeenCalledWith('New content', 'polite', undefined); announcerSpy.calls.reset(); fixture.componentInstance.politeness = 'off'; @@ -315,7 +315,7 @@ describe('CdkAriaLive', () => { invokeMutationCallbacks(); flush(); - expect(announcer.announce).toHaveBeenCalledWith('Newest content', 'assertive'); + expect(announcer.announce).toHaveBeenCalledWith('Newest content', 'assertive', undefined); })); it('should not announce the same text multiple times', fakeAsync(() => { @@ -333,6 +333,16 @@ describe('CdkAriaLive', () => { expect(announcer.announce).toHaveBeenCalledTimes(1); })); + it('should be able to pass in a duration', fakeAsync(() => { + fixture.componentInstance.content = 'New content'; + fixture.componentInstance.duration = 1337; + fixture.detectChanges(); + invokeMutationCallbacks(); + flush(); + + expect(announcer.announce).toHaveBeenCalledWith('New content', 'polite', 1337); + })); + }); @@ -349,8 +359,14 @@ class TestApp { } } -@Component({template: `
{{content}}
`}) +@Component({ + template: ` +
{{content}}
` +}) class DivWithCdkAriaLive { - @Input() politeness: AriaLivePoliteness; - @Input() content = 'Initial content'; + politeness = 'polite'; + content = 'Initial content'; + duration: number; } diff --git a/src/cdk/a11y/live-announcer/live-announcer.ts b/src/cdk/a11y/live-announcer/live-announcer.ts index 2a417482dd30..1fc123df3914 100644 --- a/src/cdk/a11y/live-announcer/live-announcer.ts +++ b/src/cdk/a11y/live-announcer/live-announcer.ts @@ -203,7 +203,7 @@ export class CdkAriaLive implements OnDestroy { // The `MutationObserver` fires also for attribute // changes which we don't want to announce. if (elementText !== this._previousAnnouncedText) { - this._liveAnnouncer.announce(elementText, this._politeness); + this._liveAnnouncer.announce(elementText, this._politeness, this.duration); this._previousAnnouncedText = elementText; } }); @@ -212,6 +212,9 @@ export class CdkAriaLive implements OnDestroy { } private _politeness: AriaLivePoliteness = 'polite'; + /** Time in milliseconds after which to clear out the announcer element. */ + @Input('cdkAriaLiveDuration') duration: number; + private _previousAnnouncedText?: string; private _subscription: Subscription | null; diff --git a/tools/public_api_guard/cdk/a11y.d.ts b/tools/public_api_guard/cdk/a11y.d.ts index 69246c1732aa..84bb15282d95 100644 --- a/tools/public_api_guard/cdk/a11y.d.ts +++ b/tools/public_api_guard/cdk/a11y.d.ts @@ -27,11 +27,12 @@ export declare const CDK_DESCRIBEDBY_HOST_ATTRIBUTE = "cdk-describedby-host"; export declare const CDK_DESCRIBEDBY_ID_PREFIX = "cdk-describedby-message"; export declare class CdkAriaLive implements OnDestroy { + duration: number; get politeness(): AriaLivePoliteness; set politeness(value: AriaLivePoliteness); constructor(_elementRef: ElementRef, _liveAnnouncer: LiveAnnouncer, _contentObserver: ContentObserver, _ngZone: NgZone); ngOnDestroy(): void; - static ɵdir: i0.ɵɵDirectiveDefWithMeta; + static ɵdir: i0.ɵɵDirectiveDefWithMeta; static ɵfac: i0.ɵɵFactoryDef; }