fix(scrolling): viewport ruler resize event running inside the NgZone (#12909)

Fixes the `resize` and `orientationchange` events from the `ViewportRuler` being run inside the `NgZone`, even though the intention is that they shouldn't be. The issue comes from the fact that we call `merge` outside the `NgZone`, however the thing that causes the event to be bound is the subscription right after it.

Fixes #12883.
This commit is contained in:
Kristiyan Kostadinov
2018-10-02 22:33:35 +02:00
committed by vivian-hu
parent 3e1cff0618
commit 707a7ee7a5
2 changed files with 19 additions and 5 deletions
+11 -1
View File
@@ -2,7 +2,7 @@ import {TestBed, inject, fakeAsync, tick} from '@angular/core/testing';
import {ScrollingModule} from './public-api';
import {ViewportRuler} from './viewport-ruler';
import {dispatchFakeEvent} from '@angular/cdk/testing';
import {NgZone} from '@angular/core';
// For all tests, we assume the browser window is 1024x786 (outerWidth x outerHeight).
// The karma config has been set to this for local tests, and it is the default size
@@ -140,5 +140,15 @@ describe('ViewportRuler', () => {
expect(spy).toHaveBeenCalledTimes(1);
subscription.unsubscribe();
}));
it('should run the resize event outside the NgZone', () => {
const spy = jasmine.createSpy('viewport changed spy');
const subscription = ruler.change(0).subscribe(() => spy(NgZone.isInAngularZone()));
dispatchFakeEvent(window, 'resize');
expect(spy).toHaveBeenCalledWith(false);
subscription.unsubscribe();
});
});
});
+8 -4
View File
@@ -36,11 +36,15 @@ export class ViewportRuler implements OnDestroy {
private _invalidateCache: Subscription;
constructor(private _platform: Platform, ngZone: NgZone) {
this._change = _platform.isBrowser ? ngZone.runOutsideAngular(() => {
return merge<Event>(fromEvent(window, 'resize'), fromEvent(window, 'orientationchange'));
}) : observableOf();
ngZone.runOutsideAngular(() => {
this._change = _platform.isBrowser ?
merge<Event>(fromEvent(window, 'resize'), fromEvent(window, 'orientationchange')) :
observableOf();
this._invalidateCache = this.change().subscribe(() => this._updateViewportSize());
// Note that we need to do the subscription inside `runOutsideAngular`
// since subscribing is what causes the event listener to be added.
this._invalidateCache = this.change().subscribe(() => this._updateViewportSize());
});
}
ngOnDestroy() {