mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
fix(a11y): aria-live directive announcing the same text multiple times (#13467)
The `CdkAriaLive` directive uses a `MutationObserver` to monitor for DOM content changes and to announce them through the `LiveAnnouncer`. Since the `MutationObserver` also fires for things like attribute changes, the same text can be announced more than once. This is visible on the calendar where the same text is announced twice when changing views.
This commit is contained in:
committed by
vivian-hu
parent
1ef16ac78a
commit
a150494202
@@ -231,6 +231,22 @@ describe('CdkAriaLive', () => {
|
||||
|
||||
expect(announcer.announce).toHaveBeenCalledWith('Newest content', 'assertive');
|
||||
}));
|
||||
|
||||
it('should not announce the same text multiple times', fakeAsync(() => {
|
||||
fixture.componentInstance.content = 'Content';
|
||||
fixture.detectChanges();
|
||||
invokeMutationCallbacks();
|
||||
flush();
|
||||
|
||||
expect(announcer.announce).toHaveBeenCalledTimes(1);
|
||||
|
||||
fixture.detectChanges();
|
||||
invokeMutationCallbacks();
|
||||
flush();
|
||||
|
||||
expect(announcer.announce).toHaveBeenCalledTimes(1);
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
@@ -131,14 +131,21 @@ export class CdkAriaLive implements OnDestroy {
|
||||
.observe(this._elementRef)
|
||||
.subscribe(() => {
|
||||
// Note that we use textContent here, rather than innerText, in order to avoid a reflow.
|
||||
const element = this._elementRef.nativeElement;
|
||||
this._liveAnnouncer.announce(element.textContent, this._politeness);
|
||||
const elementText = this._elementRef.nativeElement.textContent;
|
||||
|
||||
// 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._previousAnnouncedText = elementText;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
private _politeness: AriaLivePoliteness = 'off';
|
||||
|
||||
private _previousAnnouncedText?: string;
|
||||
private _subscription: Subscription | null;
|
||||
|
||||
constructor(private _elementRef: ElementRef, private _liveAnnouncer: LiveAnnouncer,
|
||||
|
||||
Reference in New Issue
Block a user