Skip to content

Commit 707a7ee

Browse files
crisbetovivian-hu-zz
authored andcommitted
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.
1 parent 3e1cff0 commit 707a7ee

File tree

2 files changed

+20
-6
lines changed

2 files changed

+20
-6
lines changed

src/cdk/scrolling/viewport-ruler.spec.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import {TestBed, inject, fakeAsync, tick} from '@angular/core/testing';
22
import {ScrollingModule} from './public-api';
33
import {ViewportRuler} from './viewport-ruler';
44
import {dispatchFakeEvent} from '@angular/cdk/testing';
5-
5+
import {NgZone} from '@angular/core';
66

77
// For all tests, we assume the browser window is 1024x786 (outerWidth x outerHeight).
88
// The karma config has been set to this for local tests, and it is the default size
@@ -140,5 +140,15 @@ describe('ViewportRuler', () => {
140140
expect(spy).toHaveBeenCalledTimes(1);
141141
subscription.unsubscribe();
142142
}));
143+
144+
it('should run the resize event outside the NgZone', () => {
145+
const spy = jasmine.createSpy('viewport changed spy');
146+
const subscription = ruler.change(0).subscribe(() => spy(NgZone.isInAngularZone()));
147+
148+
dispatchFakeEvent(window, 'resize');
149+
expect(spy).toHaveBeenCalledWith(false);
150+
subscription.unsubscribe();
151+
});
152+
143153
});
144154
});

src/cdk/scrolling/viewport-ruler.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,15 @@ export class ViewportRuler implements OnDestroy {
3636
private _invalidateCache: Subscription;
3737

3838
constructor(private _platform: Platform, ngZone: NgZone) {
39-
this._change = _platform.isBrowser ? ngZone.runOutsideAngular(() => {
40-
return merge<Event>(fromEvent(window, 'resize'), fromEvent(window, 'orientationchange'));
41-
}) : observableOf();
42-
43-
this._invalidateCache = this.change().subscribe(() => this._updateViewportSize());
39+
ngZone.runOutsideAngular(() => {
40+
this._change = _platform.isBrowser ?
41+
merge<Event>(fromEvent(window, 'resize'), fromEvent(window, 'orientationchange')) :
42+
observableOf();
43+
44+
// Note that we need to do the subscription inside `runOutsideAngular`
45+
// since subscribing is what causes the event listener to be added.
46+
this._invalidateCache = this.change().subscribe(() => this._updateViewportSize());
47+
});
4448
}
4549

4650
ngOnDestroy() {

0 commit comments

Comments
 (0)