The feature type returned in event handlers (extends MapGeoJSONFeature)
The feature type returned in event handlers (extends MapGeoJSONFeature)
Remove all event handlers for a specific event type.
Unregisters the callback function for the specified event type, stopping further event notifications. This is important for cleanup to prevent memory leaks and unwanted behavior.
The type of event to stop listening for
Cleanup Behavior:
When to Use:
off() then on())Best Practices:
// Remove click handlers
module.events.off('click');
// Remove all handlers
module.events.off('click');
module.events.off('hover');
module.events.off('long-hover');
module.events.off('contextmenu');
// React component cleanup
useEffect(() => {
const pois = map.pois();
pois.events.on('click', handlePoiClick);
pois.events.on('hover', handlePoiHover);
return () => {
// Cleanup on unmount
pois.events.off('click');
pois.events.off('hover');
};
}, [map]);
// Replace handler
module.events.off('click'); // Remove old handler
module.events.on('click', newHandler); // Add new handler
// Disable interactions temporarily
const savedHandler = currentHandler;
module.events.off('click'); // Disable
// ... later ...
module.events.on('click', savedHandler); // Re-enable
Register an event handler for user interactions with map features.
Attaches a callback function that will be invoked when users interact with features in this module (e.g., clicking on a POI, hovering over a route).
The type of event to listen for (click, contextmenu, hover, long-hover)
Callback function invoked when the event occurs
An unsubscribe function that removes the handler registered by this call.
Handler Parameters:
feature: The primary feature that triggered the eventlngLat: Geographic coordinates [longitude, latitude] of the eventfeatures: The features from this module at the event location, de-duplicated (for
overlapping features within the module). To inspect features across all modules, query
map.mapLibreMap.queryRenderedFeatures(...) directly — see UserEventHandler.Behavior:
on() adds a handler (it does
not replace existing ones) and all of them fire. To remove one, call the unsubscribe
this returns; to clear them all, use off(type).Performance:
// Basic click handler
module.events.on('click', (feature, lngLat, features) => {
console.log('Clicked feature:', feature.properties);
console.log('Location:', lngLat);
console.log('All features here:', features.length);
});
// Hover with tooltip
module.events.on('hover', (feature) => {
const name = feature.properties.name || 'Unnamed';
tooltip.show(name);
});
// Long-hover for detailed preview
module.events.on('long-hover', (feature) => {
// Only triggered after hovering for 300-800ms
loadPreview(feature.properties.id);
});
// Right-click context menu
module.events.on('contextmenu', (feature, lngLat) => {
event.preventDefault(); // Prevent browser context menu
showCustomMenu(lngLat, feature);
});
// Route-specific handlers
const routing = map.routing();
// Handle route line clicks
routing.events.mainLines.on('click', (route) => {
highlightRoute(route.properties.routeID);
showRouteSummary(route.properties.summary);
});
// Handle waypoint interactions
routing.events.waypoints.on('hover', (waypoint) => {
const index = waypoint.properties.index;
showTooltip(`Stop ${index + 1}`);
});
Narrows these events to part of what they cover, returning a UserEvents over just that part.
Two things can be narrowed. A feature predicate keeps only the features you care about — available on every module, since only the module's own data can tell a major incident from a minor one. A layer scope keeps only part of the map's layers; the SDK offers this where a stable, typed vocabulary for those layers exists, which today means BaseMapModule's layer groups.
A new instance, rather than this one narrowed in place: callers hold events and narrow it
more than once, and mutating would make the second where() mean "first AND second" while
leaving the surface it came from silently scoped — and its config overridden.
Narrowing on both axes is one call, not two — BaseMapModule's scope object takes a
features predicate alongside its layerGroups. A further where() does intersect with
this one, but two feature predicates read better as a single a(f) && b(f).
See EventScope — a predicate over this scope's feature type, or, where
the module supports one, a scope object such as { layerGroups }.
Optionalconfig: EventHandlerCursorConfig
Event configuration for handlers registered through the returned instance. Each scope can carry its own, which is how two parts of one module get different hover cursors. Defaults to the configuration this instance already uses.
// Feature scope: only major incidents are clickable.
trafficIncidents.events.where((incident) => incident.properties.magnitude === 'major')
.on('click', showIncidentDetails);
// Layer scope with its own cursor, on the base map.
baseMap.events
.where({ layerGroups: { mode: 'include', names: ['roadLabels'] } }, { cursorOnHover: 'pointer' })
.on('click', showRoadName);
// A named scope, narrowed by a predicate.
routing.events.tunnels.where((section) => section.properties.lengthInMeters > 500)
.on('click', showLongTunnel);
Event handling interface for map features.
Provides a simple API for attaching and removing event handlers for user interactions with map features such as clicks, hovers, and context menus. Each map module (POIs, Routing, Places, etc.) exposes an
eventsproperty that returns aUserEventsinstance.Remarks
Supported Event Types:
click: User clicks/taps on a featurecontextmenu: User right-clicks on a feature (or long-press on mobile)hover: Mouse enters a featurelong-hover: Mouse hovers over feature for configured duration (300-800ms)Event Handler Signature:
Parameters:
feature: The primary feature under the cursorlngLat: Geographic coordinates of the eventfeatures: All features at this location (when multiple overlap)Key Features:
Example
Example