Skip to content

Commit

Permalink
refactor: handle stubbed window in SSR checks (#17755)
Browse files Browse the repository at this point in the history
Uses the `isPlatformBrowser` to check whether we're rendering on the server in the `google-maps` and `youtube-player` packages, similarly to what we're doing in the CDK. This handles people stubbing out the `window`.
  • Loading branch information
crisbeto authored and jelbourn committed Nov 20, 2019
1 parent b2ea4c8 commit e2fd099
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 20 deletions.
1 change: 1 addition & 0 deletions src/google-maps/BUILD.bazel
Expand Up @@ -10,6 +10,7 @@ ng_module(
),
module_name = "@angular/google-maps",
deps = [
"@npm//@angular/common",
"@npm//@angular/core",
"@npm//@types/googlemaps",
"@npm//rxjs",
Expand Down
29 changes: 20 additions & 9 deletions src/google-maps/google-map/google-map.ts
Expand Up @@ -20,7 +20,11 @@ import {
OnInit,
Output,
ViewEncapsulation,
Optional,
Inject,
PLATFORM_ID,
} from '@angular/core';
import {isPlatformBrowser} from '@angular/common';
import {BehaviorSubject, combineLatest, Observable, Subject} from 'rxjs';
import {map, shareReplay, take, takeUntil} from 'rxjs/operators';

Expand Down Expand Up @@ -48,12 +52,6 @@ export const DEFAULT_HEIGHT = '500px';
/** Arbitrary default width for the map element */
export const DEFAULT_WIDTH = '500px';

/**
* Whether we're currently rendering inside a browser. Equivalent of `Platform.isBrowser`,
* but copied over here so we don't have to add another dependency.
*/
const isBrowser = typeof window === 'object' && !!window;

/**
* Angular component that renders a Google Map via the Google Maps JavaScript
* API.
Expand Down Expand Up @@ -194,6 +192,8 @@ export class GoogleMap implements OnChanges, OnInit, OnDestroy {
private _mapEl: HTMLElement;
_googleMap!: UpdatedGoogleMap;

/** Whether we're currently rendering inside a browser. */
private _isBrowser: boolean;
private _googleMapChanges!: Observable<google.maps.Map>;

private _listeners: google.maps.MapsEventListener[] = [];
Expand All @@ -205,8 +205,19 @@ export class GoogleMap implements OnChanges, OnInit, OnDestroy {

private readonly _destroy = new Subject<void>();

constructor(private readonly _elementRef: ElementRef) {
if (isBrowser) {
constructor(
private readonly _elementRef: ElementRef,
/**
* @deprecated `platformId` parameter to become required.
* @breaking-change 10.0.0
*/
@Optional() @Inject(PLATFORM_ID) platformId?: Object) {

// @breaking-change 10.0.0 Remove null check for `platformId`.
this._isBrowser =
platformId ? isPlatformBrowser(platformId) : typeof window === 'object' && !!window;

if (this._isBrowser) {
const googleMapsWindow: GoogleMapsWindow = window;
if (!googleMapsWindow.google) {
throw Error(
Expand All @@ -224,7 +235,7 @@ export class GoogleMap implements OnChanges, OnInit, OnDestroy {

ngOnInit() {
// It should be a noop during server-side rendering.
if (isBrowser) {
if (this._isBrowser) {
this._mapEl = this._elementRef.nativeElement.querySelector('.map-container')!;
this._setSize();

Expand Down
1 change: 1 addition & 0 deletions src/youtube-player/BUILD.bazel
Expand Up @@ -19,6 +19,7 @@ ng_module(
),
module_name = "@angular/youtube-player",
deps = [
"@npm//@angular/common",
"@npm//@angular/core",
"@npm//@types/youtube",
"@npm//rxjs",
Expand Down
29 changes: 20 additions & 9 deletions src/youtube-player/youtube-player.ts
Expand Up @@ -22,7 +22,11 @@ import {
Output,
ViewChild,
ViewEncapsulation,
Optional,
Inject,
PLATFORM_ID,
} from '@angular/core';
import {isPlatformBrowser} from '@angular/common';

import {
combineLatest,
Expand Down Expand Up @@ -72,12 +76,6 @@ interface Player extends YT.Player {
// The only field available is destroy and addEventListener.
type UninitializedPlayer = Pick<Player, 'videoId' | 'destroy' | 'addEventListener'>;

/**
* Whether we're currently rendering inside a browser. Equivalent of `Platform.isBrowser`,
* but copied over here so we don't have to add another dependency.
*/
const isBrowser = typeof window === 'object' && !!window;

/**
* Angular component that renders a YouTube player via the YouTube player
* iframe API.
Expand Down Expand Up @@ -158,15 +156,28 @@ export class YouTubePlayer implements AfterViewInit, OnDestroy, OnInit {
@ViewChild('youtubeContainer')
youtubeContainer: ElementRef<HTMLElement>;

/** Whether we're currently rendering inside a browser. */
private _isBrowser: boolean;
private _youtubeContainer = new EventEmitter<HTMLElement>();
private _destroyed = new EventEmitter<undefined>();
private _player: Player | undefined;

constructor(private _ngZone: NgZone) {}
constructor(
private _ngZone: NgZone,
/**
* @deprecated `platformId` parameter to become required.
* @breaking-change 10.0.0
*/
@Optional() @Inject(PLATFORM_ID) platformId?: Object) {

// @breaking-change 10.0.0 Remove null check for `platformId`.
this._isBrowser =
platformId ? isPlatformBrowser(platformId) : typeof window === 'object' && !!window;
}

ngOnInit() {
// Don't do anything if we're not in a browser environment.
if (!isBrowser) {
if (!this._isBrowser) {
return;
}

Expand Down Expand Up @@ -340,7 +351,7 @@ export class YouTubePlayer implements AfterViewInit, OnDestroy, OnInit {

/** See https://developers.google.com/youtube/iframe_api_reference#getPlayerState */
getPlayerState(): YT.PlayerState | undefined {
if (!isBrowser || !window.YT) {
if (!this._isBrowser || !window.YT) {
return undefined;
}

Expand Down
3 changes: 2 additions & 1 deletion tools/public_api_guard/google-maps/google-maps.d.ts
Expand Up @@ -27,7 +27,8 @@ export declare class GoogleMap implements OnChanges, OnInit, OnDestroy {
width: string;
zoom: number;
zoomChanged: EventEmitter<void>;
constructor(_elementRef: ElementRef);
constructor(_elementRef: ElementRef,
platformId?: Object);
fitBounds(bounds: google.maps.LatLngBounds | google.maps.LatLngBoundsLiteral, padding?: number | google.maps.Padding): void;
getBounds(): google.maps.LatLngBounds | null;
getCenter(): google.maps.LatLng;
Expand Down
3 changes: 2 additions & 1 deletion tools/public_api_guard/youtube-player/youtube-player.d.ts
Expand Up @@ -13,7 +13,8 @@ export declare class YouTubePlayer implements AfterViewInit, OnDestroy, OnInit {
videoId: string | undefined;
width: number | undefined;
youtubeContainer: ElementRef<HTMLElement>;
constructor(_ngZone: NgZone);
constructor(_ngZone: NgZone,
platformId?: Object);
createEventsBoundInZone(): YT.Events;
getAvailablePlaybackRates(): number[];
getAvailableQualityLevels(): YT.SuggestedVideoQuality[];
Expand Down

0 comments on commit e2fd099

Please sign in to comment.