Skip to content

Commit e4cf059

Browse files
crisbetovivian-hu-zz
authored andcommitted
refactor(live-announcer): run outside NgZone (#10631)
Switches to running the timeout from the `LiveAnnouncer` outside the `NgZone`, because it does all of its DOM manipulation directly on the element and it doesn't have to trigger Angular's change detection.
1 parent a706c8c commit e4cf059

File tree

1 file changed

+12
-8
lines changed

1 file changed

+12
-8
lines changed

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

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ export class LiveAnnouncer implements OnDestroy {
3434

3535
constructor(
3636
@Optional() @Inject(LIVE_ANNOUNCER_ELEMENT_TOKEN) elementToken: any,
37+
private _ngZone: NgZone,
3738
@Inject(DOCUMENT) _document: any) {
3839

3940
// We inject the live element and document as `any` because the constructor signature cannot
@@ -60,11 +61,13 @@ export class LiveAnnouncer implements OnDestroy {
6061
// - With Chrome and IE11 with NVDA or JAWS, a repeated (identical) message won't be read a
6162
// second time without clearing and then using a non-zero delay.
6263
// (using JAWS 17 at time of this writing).
63-
return new Promise(resolve => {
64-
setTimeout(() => {
65-
this._liveElement.textContent = message;
66-
resolve();
67-
}, 100);
64+
return this._ngZone.runOutsideAngular(() => {
65+
return new Promise(resolve => {
66+
setTimeout(() => {
67+
this._liveElement.textContent = message;
68+
resolve();
69+
}, 100);
70+
});
6871
});
6972
}
7073

@@ -77,13 +80,13 @@ export class LiveAnnouncer implements OnDestroy {
7780
private _createLiveElement(): HTMLElement {
7881
const elementClass = 'cdk-live-announcer-element';
7982
const previousElements = this._document.getElementsByClassName(elementClass);
83+
const liveEl = this._document.createElement('div');
8084

8185
// Remove any old containers. This can happen when coming in from a server-side-rendered page.
8286
for (let i = 0; i < previousElements.length; i++) {
8387
previousElements[i].parentNode!.removeChild(previousElements[i]);
8488
}
8589

86-
const liveEl = this._document.createElement('div');
8790
liveEl.classList.add(elementClass);
8891
liveEl.classList.add('cdk-visually-hidden');
8992

@@ -146,8 +149,8 @@ export class CdkAriaLive implements OnDestroy {
146149

147150
/** @docs-private @deprecated @breaking-change 7.0.0 */
148151
export function LIVE_ANNOUNCER_PROVIDER_FACTORY(
149-
parentDispatcher: LiveAnnouncer, liveElement: any, _document: any) {
150-
return parentDispatcher || new LiveAnnouncer(liveElement, _document);
152+
parentDispatcher: LiveAnnouncer, liveElement: any, _document: any, ngZone: NgZone) {
153+
return parentDispatcher || new LiveAnnouncer(liveElement, _document, ngZone);
151154
}
152155

153156

@@ -159,6 +162,7 @@ export const LIVE_ANNOUNCER_PROVIDER: Provider = {
159162
[new Optional(), new SkipSelf(), LiveAnnouncer],
160163
[new Optional(), new Inject(LIVE_ANNOUNCER_ELEMENT_TOKEN)],
161164
DOCUMENT,
165+
NgZone,
162166
],
163167
useFactory: LIVE_ANNOUNCER_PROVIDER_FACTORY
164168
};

0 commit comments

Comments
 (0)