Skip to content

Commit

Permalink
refactor(input): run autofill monitor outside the NgZone
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
crisbeto committed Mar 12, 2018
1 parent 6273d6a commit 5d22f60
Showing 1 changed file with 11 additions and 6 deletions.
17 changes: 11 additions & 6 deletions src/lib/input/autofill.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ import {
Injectable,
OnDestroy,
OnInit,
Output
Output,
NgZone,
} from '@angular/core';
import {Observable} from 'rxjs/Observable';
import {empty as observableEmpty} from 'rxjs/observable/empty';
Expand Down Expand Up @@ -50,7 +51,7 @@ const listenerOptions: any = supportsPassiveEventListeners() ? {passive: true} :
export class AutofillMonitor implements OnDestroy {
private _monitoredElements = new Map<Element, MonitoredElementInfo>();

constructor(private _platform: Platform) {}
constructor(private _platform: Platform, private _ngZone: NgZone) {}

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

const info = this._monitoredElements.get(element);

if (info) {
return info.subject.asObservable();
}
Expand All @@ -71,15 +73,17 @@ export class AutofillMonitor implements OnDestroy {
const listener = (event: AnimationEvent) => {
if (event.animationName === 'mat-input-autofill-start') {
element.classList.add('mat-input-autofilled');
result.next({target: event.target as Element, isAutofilled: true});
this._ngZone.run(() => result.next({target: event.target as Element, isAutofilled: true}));
} else if (event.animationName === 'mat-input-autofill-end') {
element.classList.remove('mat-input-autofilled');
result.next({target: event.target as Element, isAutofilled: false});
this._ngZone.run(() => result.next({target: event.target as Element, isAutofilled: false}));
}
};

element.addEventListener('animationstart', listener, listenerOptions);
element.classList.add('mat-input-autofill-monitored');
this._ngZone.runOutsideAngular(() => {
element.addEventListener('animationstart', listener, listenerOptions);
element.classList.add('mat-input-autofill-monitored');
});

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

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

0 comments on commit 5d22f60

Please sign in to comment.