Home | Send Feedback

YouTube Player and Google Maps Angular component

Published: 21. April 2020  •  Updated: 21. May 2021  •  javascript, angular

In this blog post, we take a look at two components from the angular/component repository: Angular Google Maps component and Angular YouTube Player component.

In the past, the angular/component repository was named angular/material and hosted only the Material Design components. Over time other components were added to the repository like the Component Dev Kit (CDK), the YouTube Player and Google Maps component. The Angular developers decided in 2019 to rename the repository to angular/component to emphasize the fact that this repository is not just the home for the Material Design components but also other components.

The two components we take a look in this blog post were wrappers around existing JavaScript libraries: Google Maps API and YouTube IFrame Player API.

Demo program

The demo application I wrote for this blog post is a trivial example that displays a Google map with several hardcoded markers. A click on the markers opens an info window and plays a YouTube video from this location.

demo

You find the complete source code on GitHub:
https://github.com/ralscha/blog2020/tree/master/locationvideo

The demo application is online under this address:
https://omed.hplar.ch/locationvideo/

Google Maps component

This is an Angular component that wraps the Google Maps API JavaScript library.

Setup

Install the component

npm install @angular/google-maps

You need an API key from Google to access Google Maps. Follow these steps to get a key:
https://developers.google.com/maps/get-started

Before you can use the Angular component, you need to load the Google Maps JavaScript API. The Google Maps JavaScript API must be loaded before the GoogleMap Angular component. In the demo application, I added a <script> tag to index.html

<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAZ..."></script>

Finally, import GoogleMapsModule into your Angular application.

import {GoogleMapsModule} from '@angular/google-maps';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    GoogleMapsModule,   // <------
    ...
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule {
}

Usage

The Angular Google Maps library provides multiple components that wrap classes from the Google Maps JavaScript API.

In this blog post, I focus on the three components, google-map, map-marker, and map-info-window.


google-map

You can configure the map with the [options] input property. It accepts a google.maps.MapOptions object.

The component provides convenience inputs for setting the [center] and [zoom] without creating an entire google.maps.MapOptions object.

To specify the size, pass string values to the inputs [height] and [width].


The following events from the underlying google.maps.Map class are supported:


The component provides the following methods. You can access these in your TypeScript code when you reference the component with @ViewChild.


map-marker

The MapMarker component displays a marker on the map. It has to be a content child of a GoogleMap component. It provides the [options] input to configure the component. This input accepts a google.maps.MarkerOptions object.

Alternatively, you can configure the component with the convenience inputs [title], [position], [label], and [clickable] without creating an entire google.maps.MarkerOptions object.


The component emits the following events.


The component provides the following methods.


map-info-window

The MapInfoWindow component displays an info window. Like the two components above, it provides an [options] input to configure the component. This input property accepts a google.maps.InfoWindowOptions object.

You can also set the position with the convenience [position] input, without creating an entire google.maps.InfoWindowOptions object.

The content of the component is used as the content for the info window. It keeps the structure and CSS styles when displayed as info. The MapInfoWindow component must be a child of a GoogleMap component, and you must call the open() method to display the info. This method accepts a MapMarker object as optional argument. If provided, the info window appears next to the marker. If omitted, the position property of the options input is used.


The component emits the following events.


The component provides the following methods.


Demo application

The TypeScript code defines a hardcoded array of marker objects with the marker option, the YouTube video id, and a text that is displayed in the info window when the user clicks on the marker.

type MarkerObject = {
  option: google.maps.MarkerOptions,
  position: google.maps.LatLngLiteral,
  videoId: string,
  info: string
};

  markers: MarkerObject[] = [{
    option: {title: 'Paradise Beach', position: {lat: 13.6131648, lng: 98.1379005}},
    videoId: '85tl3vKF6sw',
    info: 'Paradise Beach, one of the most pristine beach in Myanmar'
  }, {
    option: {title: 'Hpa-An / Mawlamyine', position: {lat: 16.8841401, lng: 97.6160162}},
    videoId: 'vnWP7rhHAJU',
    info: 'Aerial view of Hpa-An and Mawlamyine.'
  }, {
  ...

The class additionally defines the latitude and longitude of the map centre, the zoom level and the property info that is used for displaying the information in the info window.

  center = {lat: 19.689138, lng: 95.970246};
  zoom = 6;
  info: string | null = null;

app.component.ts

The code in the template passes the variables from TypeScript to the Google Maps components. It loops over the marker objects and creates map-marker components, and it creates one info window bound to the info property of the class. This way we can dynamically change the content of the info window.

<google-map [center]="center" [zoom]="zoom" height="100%" width="100%">
  <map-marker #markerElement="mapMarker"
              (mapClick)="openInfoWindow(markerElement, marker)"
              *ngFor="let marker of markers"
              [options]="marker.option"></map-marker>
  <map-info-window>{{info}}</map-info-window>
</google-map>

app.component.html

When the user clicks on a marker, the component fires the mapClick event, which calls the openInfoWindow() method. The application passes a reference to the map-marker element and the custom marker object to this method. The method then assigns the info property from the custom marker object to the info property of the class, and then programmatically opens the info window with open(). By passing the reference to the map-marker element, the info window appears at the position of the clicked marker.

  @ViewChild(MapInfoWindow) infoWindow: MapInfoWindow;

  openInfoWindow(markerElement: MapMarker, marker: MarkerObject) {
    ...
    this.info = marker.info;
    this.infoWindow.open(markerElement);
  }

More information

To learn more about the Google Maps component check out the project readme
https://github.com/angular/components/tree/main/src/google-maps

and the Google Maps JavaScript API documentation https://developers.google.com/maps/documentation/javascript/overview


YouTube Player component

This is an Angular component that wraps the YouTube IFrame Player API JavaScript library.

Setup

Install the component

npm install @angular/youtube-player

Import YouTubePlayerModule into your Angular application.

import {YouTubePlayerModule} from '@angular/youtube-player';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    ...
    YouTubePlayerModule  // <---------
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule {
}

Load the JavaScript API. The demo application does this by dynamically creating a <script> tag in ngOnInit(). The YouTube JavaScript API does not require an API key.

  ngOnInit(): void {
    const tag = document.createElement('script');
    tag.src = 'https://www.youtube.com/iframe_api';
    document.body.appendChild(tag);
  }

app.component.ts

For more information, check out the Getting Started guide.


Usage

The library provides the component <youtube-player> you can add to your template. To play a video, you need to assign a valid id to the videoId input property.

<youtube-player videoId="HabG0k6Ycvw"></youtube-player>

You find this id in the address bar of your browser when you watch a YouTube video. It's the value of the v query parameter.

videoId


Input

You may change the width and height of the player window with the input properties [height] and [width]. Both properties expect a number (pixels).

With the input properties [startSeconds] and [endSeconds], you can specify at what moment in the video the player should start respectively end. Both properties expect a number (seconds).

With the input property [suggestedQuality] you can specify the desired video quality. You can pass the following values to this input property:


Events

The youtube-player component emits the following events.

(ready)
This event fires whenever the player has finished loading. The event object is of type YT.PlayerEvent and the target property is a reference to the YT.Player

(stateChange)
This event fires whenever the player's state changes. The event object is of type YT.OnStateChangeEvent and provides a data property which is a number describing the new player state:

When the player first loads a video, it broadcasts an unstarted (-1) event. When a video is cued and ready to play, the player broadcasts a video cued (5) event.


(error)
This event fires if an error occurs in the player. The event object is of type YT.OnErrorEvent and provides a data property which is a number specifying the error code:


(playbackQualityChange)
This event fires whenever the video playback quality changes. The event object is of type YT.OnPlaybackQualityChangeEvent and provides a data property, which is a string identifying the new playback quality. These are the same values you can pass to the [suggestedQuality] input property.

(playbackRateChange)
This event fires whenever the video playback rate changes. The event is of type YT.OnPlaybackRateChangeEvent and provides a data property which is a number identifying the new playback rate.


Methods

The component class YouTubePlayer provides several methods, you can call from TypeScript to programmatically control the player.

Play, pause, and stop the video:

Volume

Playback rate

Playback status

Video information


Demo application

The demo application uses the following code in the template.

<youtube-player (ready)="onReady($event)" (stateChange)="onStateChange($event)"
                *ngIf="videoId"
                [videoId]="videoId"></youtube-player>

app.component.html

The component is hidden until the user selects a marker. The component listens for the ready and stateChange event.

The TypeScript code references the component with @ViewChild

  videoId: string | null = null;

  @ViewChild(YouTubePlayer) youtubePlayer!: YouTubePlayer;

app.component.ts

When the user clicks on a marker the application checks if there is currently a video playing and stops it.

  openInfoWindow(markerElement: MapMarker, marker: MarkerObject): void {
    if (this.youtubePlayer
      && this.youtubePlayer.getPlayerState() === YT.PlayerState.PLAYING) {
      this.youtubePlayer.stopVideo();
    }

app.component.ts

The ready and stateChange event handlers are responsible for starting the video as soon as it's loaded. The first time the application sets the videoId property, it displays the component and emits the ready event. The video is cued at this stage, so the component does not emit the stateChange event.

Following changes of the videoId trigger only the stateChange event. This event handler is called multiple times. As soon as the state is YT.PlayerState.CUED (5) the video is ready for playback.

  onReady(event: YT.PlayerEvent): void {
    event.target.playVideo();
  }

  onStateChange(event: YT.OnStateChangeEvent): void {
    if (event.data === YT.PlayerState.CUED) {
      event.target.playVideo();
    }
  }

app.component.ts


More information

Check out the project readme and the JavaScript API documentation if you want to learn more about the YouTube Player component

Project readme:
https://github.com/angular/components/tree/main/src/youtube-player

YouTube IFrame Player API:
https://developers.google.com/youtube/iframe_api_reference