fix(viewport-ruler): fix server-side rendering errors when attempting to measure the viewport (#9870)

Fixes some errors being thrown by the `ViewportRuler` when attempting to measure the viewport or to get the scroll position while rendering on the server.

Relates to #9066.
This commit is contained in:
Kristiyan Kostadinov
2018-02-13 16:40:07 +01:00
committed by Jeremy Elbourn
parent 87bbfc52c8
commit 10e26a5311
2 changed files with 29 additions and 11 deletions
+19 -4
View File
@@ -33,8 +33,8 @@ export class ViewportRuler implements OnDestroy {
/** Subscription to streams that invalidate the cached viewport dimensions. */
private _invalidateCache: Subscription;
constructor(platform: Platform, ngZone: NgZone) {
this._change = platform.isBrowser ? ngZone.runOutsideAngular(() => {
constructor(private _platform: Platform, ngZone: NgZone) {
this._change = _platform.isBrowser ? ngZone.runOutsideAngular(() => {
return merge<Event>(fromEvent(window, 'resize'), fromEvent(window, 'orientationchange'));
}) : observableOf();
@@ -51,7 +51,14 @@ export class ViewportRuler implements OnDestroy {
this._updateViewportSize();
}
return {width: this._viewportSize.width, height: this._viewportSize.height};
const output = {width: this._viewportSize.width, height: this._viewportSize.height};
// If we're not on a browser, don't cache the size since it'll be mocked out anyway.
if (!this._platform.isBrowser) {
this._viewportSize = null!;
}
return output;
}
/** Gets a ClientRect for the viewport's bounds. */
@@ -80,6 +87,12 @@ export class ViewportRuler implements OnDestroy {
/** Gets the (top, left) scroll position of the viewport. */
getViewportScrollPosition() {
// While we can get a reference to the fake document
// during SSR, it doesn't have getBoundingClientRect.
if (!this._platform.isBrowser) {
return {top: 0, left: 0};
}
// The top-left-corner of the viewport is determined by the scroll position of the document
// body, normally just (scrollLeft, scrollTop). However, Chrome and Firefox disagree about
// whether `document.body` or `document.documentElement` is the scrolled element, so reading
@@ -107,7 +120,9 @@ export class ViewportRuler implements OnDestroy {
/** Updates the cached viewport size. */
private _updateViewportSize() {
this._viewportSize = {width: window.innerWidth, height: window.innerHeight};
this._viewportSize = this._platform.isBrowser ?
{width: window.innerWidth, height: window.innerHeight} :
{width: 0, height: 0};
}
}
+10 -7
View File
@@ -42,8 +42,7 @@ import {
CdkTableModule,
DataSource
} from '@angular/cdk/table';
import {Overlay} from '@angular/cdk/overlay';
import {ViewportRuler} from '@angular/cdk/scrolling';
import {of as observableOf} from 'rxjs/observable/of';
import {Observable} from 'rxjs/Observable';
@@ -75,13 +74,17 @@ export class KitchenSink {
/** Data source for the CDK and Material table. */
tableDataSource = new TableDataSource();
constructor(snackBar: MatSnackBar, dialog: MatDialog, overlay: Overlay) {
// Open a snack bar to do a basic sanity check of the overlays.
constructor(
snackBar: MatSnackBar,
dialog: MatDialog,
viewportRuler: ViewportRuler) {
snackBar.open('Hello there');
dialog.open(TestDialog);
// TODO(crisbeto): use the noop scroll strategy until
// the fixes for the block scroll strategy get in.
dialog.open(TestDialog, {scrollStrategy: overlay.scrollStrategies.noop()});
// Do a sanity check on the viewport ruler.
viewportRuler.getViewportRect();
viewportRuler.getViewportSize();
viewportRuler.getViewportScrollPosition();
}
}