Skip to content

Commit 5d22f60

Browse files
committed
refactor(input): run autofill monitor outside the NgZone
Switches the autofill monitor to run outside the `NgZone`, because it toggles classes on the element directly and it has the potential of being fired very often if the user has other animations on the element. Also adds a description to an output that is part of the public API.
1 parent 6273d6a commit 5d22f60

File tree

1 file changed

+11
-6
lines changed

1 file changed

+11
-6
lines changed

src/lib/input/autofill.ts

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ import {
1414
Injectable,
1515
OnDestroy,
1616
OnInit,
17-
Output
17+
Output,
18+
NgZone,
1819
} from '@angular/core';
1920
import {Observable} from 'rxjs/Observable';
2021
import {empty as observableEmpty} from 'rxjs/observable/empty';
@@ -50,7 +51,7 @@ const listenerOptions: any = supportsPassiveEventListeners() ? {passive: true} :
5051
export class AutofillMonitor implements OnDestroy {
5152
private _monitoredElements = new Map<Element, MonitoredElementInfo>();
5253

53-
constructor(private _platform: Platform) {}
54+
constructor(private _platform: Platform, private _ngZone: NgZone) {}
5455

5556
/**
5657
* Monitor for changes in the autofill state of the given input element.
@@ -63,6 +64,7 @@ export class AutofillMonitor implements OnDestroy {
6364
}
6465

6566
const info = this._monitoredElements.get(element);
67+
6668
if (info) {
6769
return info.subject.asObservable();
6870
}
@@ -71,15 +73,17 @@ export class AutofillMonitor implements OnDestroy {
7173
const listener = (event: AnimationEvent) => {
7274
if (event.animationName === 'mat-input-autofill-start') {
7375
element.classList.add('mat-input-autofilled');
74-
result.next({target: event.target as Element, isAutofilled: true});
76+
this._ngZone.run(() => result.next({target: event.target as Element, isAutofilled: true}));
7577
} else if (event.animationName === 'mat-input-autofill-end') {
7678
element.classList.remove('mat-input-autofilled');
77-
result.next({target: event.target as Element, isAutofilled: false});
79+
this._ngZone.run(() => result.next({target: event.target as Element, isAutofilled: false}));
7880
}
7981
};
8082

81-
element.addEventListener('animationstart', listener, listenerOptions);
82-
element.classList.add('mat-input-autofill-monitored');
83+
this._ngZone.runOutsideAngular(() => {
84+
element.addEventListener('animationstart', listener, listenerOptions);
85+
element.classList.add('mat-input-autofill-monitored');
86+
});
8387

8488
this._monitoredElements.set(element, {
8589
subject: result,
@@ -118,6 +122,7 @@ export class AutofillMonitor implements OnDestroy {
118122
selector: '[matAutofill]',
119123
})
120124
export class MatAutofill implements OnDestroy, OnInit {
125+
/** Emits when the autofill state of the element changes. */
121126
@Output() matAutofill: EventEmitter<AutofillEvent> = new EventEmitter<AutofillEvent>();
122127

123128
constructor(private _elementRef: ElementRef, private _autofillMonitor: AutofillMonitor) {}

0 commit comments

Comments
 (0)