Use Maptoolkit with ngx-maplibre-gl in Angular
ngx-maplibre-gl wraps MapLibre GL JS in Angular
components. A Maptoolkit style URL goes into the mapStyle input; the style names its own tile
sources and carries its own attribution.
Install
npm install @maplibre/ngx-maplibre-gl maplibre-glVersion 22 requires Angular 22 and MapLibre GL JS 6.
The component
import { Component } from "@angular/core";
import { MapComponent, MarkerComponent, ControlComponent, NavigationControlDirective } from "@maplibre/ngx-maplibre-gl";
@Component({
selector: "app-maplibre-map",
imports: [MapComponent, MarkerComponent, ControlComponent, NavigationControlDirective],
template: `
<mgl-map
class="map"
[mapStyle]="style"
[center]="[11.4041, 47.2692]"
[zoom]="12"
[attributionControl]="{ compact: false }"
>
<mgl-control mglNavigation position="top-right" />
<mgl-marker [lngLat]="[11.4041, 47.2692]" />
</mgl-map>
`,
styles: `.map { height: 400px; }`,
})
export class MaplibreMap {
style = "https://styles.maptoolkit.net/maptoolkit/maptoolkit.summer.json?api_key=YOUR_API_KEY";
}- The style input is
mapStyle, andzoomis a number. Older tutorials show[style]and[zoom]="[12]"; with version 22 both fail to compile. <mgl-control mglNavigation>needs two imports,ControlComponentfor the element andNavigationControlDirectivefor the attribute. With only the directive, the page throwsNG0201: No provider for ControlComponent found.attributionControlwithcompact: falsekeeps the credit visible. By default MapLibre collapses it into an icon as soon as the user interacts with the map.mgl-mapneeds a height, or the map renders nothing and reports no error.
Serve the MapLibre worker
MapLibre 6 loads its web worker from a separate file at runtime, which an Angular build does not emit. Without the setup below, the map stays blank and never finishes loading. ngx-maplibre-gl documents the fix: copy the worker into the build output, then tell the library where it is.
In angular.json, add both files to assets, together, because the worker imports the second one
from its own directory. Add MapLibre’s stylesheet to styles while you are there:
"styles": [
"node_modules/maplibre-gl/dist/maplibre-gl.css",
"src/styles.css"
],
"assets": [
{ "glob": "**/*", "input": "public" },
{ "glob": "maplibre-gl-worker.mjs", "input": "node_modules/maplibre-gl/dist", "output": "/" },
{ "glob": "maplibre-gl-shared.mjs", "input": "node_modules/maplibre-gl/dist", "output": "/" }
]In app.config.ts:
import { ApplicationConfig } from "@angular/core";
import { provideMaplibreWorker } from "@maplibre/ngx-maplibre-gl/config";
export const appConfig: ApplicationConfig = {
providers: [provideMaplibreWorker("maplibre-gl-worker.mjs")],
};The provider applies the URL right before the first map is created, relative to the page’s base URL, so it also works when the app is deployed under a sub-path.
Keep the map out of the initial bundle
The map component comes to about 1.08 MB, over Angular’s default 1 MB budget for the initial
bundle, so a direct import fails the production build. Wrap the map in @defer where you use it:
@defer {
<app-maplibre-map />
} @placeholder {
<div style="height: 400px"></div>
}The Maps JS Angular page has the measurements and the trade-off against raising the budget.
Next steps
Sources and layers are components as well, mgl-geojson-source and mgl-layer, and mgl-layer
takes the same paint and layout objects as MapLibre’s addLayer(). The per-API MapLibre
examples carry over directly: a route from the Routing API, or
relief from Terrain Tiles.