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()inngOnDestroyfrees 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
ngAfterViewInitafter the map is created.