Skip to content

Use Maptoolkit Tiles with ngx-leaflet in Angular

ngx-leaflet turns an element into a Leaflet map with the leaflet directive. Maptoolkit raster tiles go in as an ordinary Leaflet tileLayer, so the map options are plain Leaflet code.

Install

npm install leaflet @bluehalo/ngx-leaflet
npm install --save-dev @types/leaflet

The ngx-leaflet major version follows Angular’s: version 22 for Angular 22.

The component

import { Component } from "@angular/core";
import { LeafletDirective } from "@bluehalo/ngx-leaflet";
import { latLng, tileLayer, marker, Icon, Map } from "leaflet";

// angular.json copies Leaflet's marker images to /leaflet/, see below.
Icon.Default.imagePath = "leaflet/";

@Component({
  selector: "app-leaflet-map",
  imports: [LeafletDirective],
  template: `<div class="map" leaflet [leafletOptions]="options" (leafletMapReady)="onMapReady($event)"></div>`,
  styles: `.map { height: 400px; }`,
})
export class LeafletMap {
  options = {
    layers: [
      tileLayer("https://rtc-cdn.maptoolkit.net/rtc/maptoolkit-maptoolkit.summer/{z}/{x}/{y}{r}.png?api_key=YOUR_API_KEY", {
        maxZoom: 18,
        attribution: '&copy; <a href="https://www.maptoolkit.com">Maptoolkit</a> &copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>',
      }),
      marker([47.2692, 11.4041]).bindPopup("Innsbruck"),
    ],
    zoom: 13,
    center: latLng(47.2692, 11.4041),
  };

  onMapReady(map: Map) {
    // The Leaflet map, for anything the options do not cover.
  }
}
  • leafletOptions is read once, when the map is created. For later changes, keep the Map from leafletMapReady and call Leaflet on it, such as map.flyTo().
  • {r} is Leaflet’s retina placeholder. It becomes @2x on high-density screens, and Maptoolkit serves both tile sizes from the same URL.
  • The attribution option is required. Raster tiles carry no credit of their own.
  • The element needs a height, or the map is zero pixels tall.

angular.json: the stylesheet and the marker images

Two additions to the build target. The stylesheet goes into styles; without it the tiles render as a scattered mosaic. The marker images go into assets:

"styles": [
  "node_modules/leaflet/dist/leaflet.css",
  "src/styles.css"
],
"assets": [
  { "glob": "**/*", "input": "public" },
  { "glob": "*.png", "input": "node_modules/leaflet/dist/images", "output": "leaflet/" }
]

Leaflet looks for its default marker icon next to its stylesheet. After an Angular build that path does not exist, and the marker shows as a broken image while the browser requests /marker-icon.png and gets 404. The assets entry copies the images to /leaflet/, and Icon.Default.imagePath = "leaflet/" in the component tells Leaflet to look there.

Bundle size

Leaflet is small enough for Angular’s default build budget: about 156 kB for the map component in a test app, against the 1 MB limit for the initial bundle. A @defer block around the map is optional here, unlike with the WebGL libraries described on the Maps JS Angular page.

Next steps

Your own data goes in as more entries in layers, or through leafletLayers if the list changes at runtime. The Leaflet GeoJSON example shows per-feature styling and popups, and its L.geoJSON(...) call works unchanged inside layers.