Skip to content

Use Maptoolkit Maps in Angular

A map in Angular is a standalone component with a viewChild for the container, the map created in ngAfterViewInit and removed in ngOnDestroy. The one Angular-specific trap is the build budget: the map library alone is larger than the default limit for the initial bundle.

The component

import { Component, ElementRef, AfterViewInit, OnDestroy, viewChild } from "@angular/core";
import { Map } from "@maptoolkit/maps";

@Component({
  selector: "app-maptoolkit-map",
  template: `<div #container class="map"></div>`,
  styles: `.map { width: 100%; height: 400px; }`,
})
export class MaptoolkitMap implements AfterViewInit, OnDestroy {
  private container = viewChild.required<ElementRef<HTMLDivElement>>("container");
  private map?: Map;

  ngAfterViewInit() {
    this.map = new Map({
      container: this.container().nativeElement,
      apiKey: "YOUR_API_KEY",
      center: [11.4041, 47.2692],
      zoom: 12,
    });
  }

  ngOnDestroy() {
    this.map?.remove();
  }
}
  • The map is created in ngAfterViewInit, the first hook in which the container element exists.
  • remove() in ngOnDestroy frees the WebGL context. Browsers allow only a handful of live contexts, and a map that is never removed keeps its context after the route changes.
  • The container needs a height, or the map initializes into a zero-pixel element with no error.

The stylesheet

Add the Maptoolkit stylesheet to the styles array of the build target in angular.json, so it is loaded once for the whole app:

"styles": [
  "node_modules/@maptoolkit/maps/dist/maptoolkit.css",
  "src/styles.css"
]

Keep the map out of the initial bundle

A new Angular project fails its production build as soon as a component imports Maptoolkit Maps JS directly:

bundle initial exceeded maximum budget. Budget 1.00 MB was not met by 363.73 kB with a total of 1.36 MB.

The library is about 1.07 MB on its own, over the default 1 MB limit for the initial bundle. Wrap the map in a @defer block where you use it:

@defer {
  <app-maptoolkit-map />
} @placeholder {
  <div style="height: 400px"></div>
}

Angular then builds the map component into its own chunk and loads it after the page. In a test app this took the initial bundle down to 328 kB, with the map as a 1.07 MB lazy chunk. The placeholder keeps the page from jumping when the map appears; give it the map’s height.

Raising the budget in angular.json also makes the build pass, but then the map library has to download before the page first renders.

Next steps

  • With a wrapper library, use ngx-leaflet for raster tiles or ngx-maplibre-gl for MapLibre GL JS.
  • Maps JS Examples for what to do with the map once it is mounted; the code goes into ngAfterViewInit after the map is created.