Skip to content

MapLibreGL

The root map component. Renders a MapLibre GL JS map and yields pre-bound child components for adding sources, layers, markers, popups, controls, and event listeners.

The block is only rendered after the map has fully loaded.

Import

ts
import MapLibreGL from 'ember-maplibre-gl/components/maplibre-gl';

Example

gts
<MapLibreGL
  @initOptions={{hash style="https://demotiles.maplibre.org/style.json" center=(array 0 0) zoom=1}}
  @mapLoaded={{this.onMapLoaded}}
  as |map|
>
  <map.source @options={{this.geojsonSource}} as |source|>
    <source.layer @options={{this.circleLayer}} />
  </map.source>
  <map.marker @lngLat={{this.markerPosition}} />
  <map.on @event="click" @action={{this.onClick}} />
</MapLibreGL>

Signature

ts
interface MapLibreGLSignature {
    Element: HTMLDivElement;
    Args: {
        /**
         * MapLibre map options (style, center, zoom, etc.). Passed once at construction; later changes are ignored.
         * The `container` property is managed internally and should be omitted.
         *
         * @see https://maplibre.org/maplibre-gl-js/docs/API/type-aliases/MapOptions/
         */
        initOptions: Omit<MapOptions, 'container'>;
        /** Called once the map's style and tiles have loaded. Receives the map instance. */
        mapLoaded?: (map: MaplibreMap) => void;
        /**
         * Cache the WebGL map instance on teardown and reuse it on remount.
         * Avoids expensive context creation on repeated route transitions.
         * Only works when `initOptions.style` is a URL string.
         */
        reuseMaps?: boolean;
        /** Override the map constructor (e.g. for testing or mapbox-gl compatibility). */
        mapLib?: new (...args: unknown[]) => MaplibreMap;
    };
    Blocks: {
        /**
         * Yields an object with pre-bound child components and the map instance.
         * Available after the map has loaded.
         */
        default: [
            {
                /** Invoke a method on the map instance declaratively. */
                call: WithBoundArgs<typeof MapLibreGLCall, 'obj'>;
                /** Add a UI control (navigation, scale, etc.) to the map. */
                control: WithBoundArgs<typeof MapLibreGLControl, 'map' | 'parent'>;
                /** Load and register a custom image for use in symbol layers. */
                image: WithBoundArgs<typeof MapLibreGLImage, 'map' | 'parent'>;
                /** Add a rendering layer directly (without an explicit source component). */
                layer: WithBoundArgs<typeof MapLibreGLLayer, 'map' | 'parent'>;
                /** Place a draggable marker on the map. */
                marker: WithBoundArgs<typeof MapLibreGLMarker, 'map' | 'parent'>;
                /** Bind an event listener to the map. */
                on: WithBoundArgs<typeof MapLibreGLOn, 'eventSource'>;
                /** Show a popup overlay on the map. */
                popup: WithBoundArgs<typeof MapLibreGLPopup, 'map'>;
                /** Add a data source (GeoJSON, vector tiles, etc.) to the map. */
                source: WithBoundArgs<typeof MapLibreGLSource, 'map' | 'parent'>;
                /** The underlying MapLibre map instance (always defined inside the default block). */
                instance: MaplibreMap | undefined;
                /** The Ember component instance (useful for associateDestroyableChild). */
                component: MapLibreGL;
            }
        ];
        /** Yielded when the map encounters a fatal error (e.g. WebGL context lost). Receives an `Error` with a `.message` property. */
        error: [Error];
    };
}

Args

ArgTypeRequiredDescription
initOptionsOmit<MapOptions, 'container'>YesMapLibre map options (style, center, zoom, etc.). Passed once at construction; later changes are ignored. The container property is managed internally and should be omitted.
mapLoadedFunctionNoCalled once the map's style and tiles have loaded. Receives the map instance.
reuseMapsbooleanNoCache the WebGL map instance on teardown and reuse it on remount. Avoids expensive context creation on repeated route transitions. Only works when initOptions.style is a URL string.
mapLibMapConstructorNoOverride the map constructor (e.g. for testing or mapbox-gl compatibility).

Yields

PropertyTypeDescription
callMapLibreGLCallInvoke a method on the map instance declaratively.
controlMapLibreGLControlAdd a UI control (navigation, scale, etc.) to the map.
imageMapLibreGLImageLoad and register a custom image for use in symbol layers.
layerMapLibreGLLayerAdd a rendering layer directly (without an explicit source component).
markerMapLibreGLMarkerPlace a draggable marker on the map.
onMapLibreGLOnBind an event listener to the map.
popupMapLibreGLPopupShow a popup overlay on the map.
sourceMapLibreGLSourceAdd a data source (GeoJSON, vector tiles, etc.) to the map.
instance`MaplibreMapundefined`
componentMapLibreGLThe Ember component instance (useful for associateDestroyableChild).

Demo

gts
import MapLibreGL from 'ember-maplibre-gl/components/maplibre-gl';

const options = {
  style: 'https://tiles.openfreemap.org/styles/bright',
  center: [12.5, 41.88],
  zoom: 5,
};

<template>
  <MapLibreGL
    @initOptions={{options}}
    style="height: 300px; width: 100%; border-radius: 8px;"
  />
</template>

Error Handling

The component supports an error named block. The yielded value is an Error object with a .message property:

hbs
<MapLibreGL @initOptions={{this.options}}>
  <:default as |map|>
    <!-- map content -->
  </:default>
  <:error as |error|>
    <p>Map failed to load: {{error.message}}</p>
  </:error>
</MapLibreGL>

Custom Map Constructor

The @mapLib arg lets you swap in a different map constructor. This is useful for:

  • Testing — pass a mock/stub constructor to avoid WebGL in tests
  • Mapbox GL JS — in theory, Mapbox's Map class could work since MapLibre forked from it, but API drift means this is not guaranteed
  • Custom subclasses — extend maplibregl.Map with project-specific behavior
gts
import MapLibreGL from 'ember-maplibre-gl/components/maplibre-gl';
import { Map as CustomMap } from 'some-maplibre-fork';

const options = { style: '...', center: [0, 0], zoom: 2 };

<template>
  <MapLibreGL @initOptions={{options}} @mapLib={{CustomMap}} />
</template>

WARNING

The constructor must be API-compatible with maplibregl.Map. Passing an incompatible constructor will likely cause runtime errors in sub-components that call MapLibre-specific methods.