Skip to main content

alphaThis is a new frontend component. Help us improve it and give your feedback on Slack.

Place a marker to continue

Use the interact plugin's placeMarker mode to let users drop a location pin on the map before continuing a journey.

Two patterns work together in this example:

  • Hybrid behaviour with built-in back and continue — on mobile the map opens fullscreen and the backAndContinue option renders Back and Continue buttons inside the map. The Continue button is enabled declaratively via continueEnabledWhen once a marker has been placed.
  • External Continue button for inline — when the map is inline (tablet/desktop), a Continue button sits outside the map container. It uses app:opened, app:closed, and app:fullscreenchange to show and hide in sync with the map's display mode, and interact:markerchange to enable once a marker is placed.
The map requires JavaScript to be enabled.
import InteractiveMap from '@defra/interactive-map'
import maplibreProvider from '@defra/interactive-map/providers/maplibre'
import createInteractPlugin from '@defra/interactive-map/plugins/interact'
const interactPlugin = createInteractPlugin({
interactionModes: ['placeMarker']
})
const map = new InteractiveMap('my-map', {
behaviour: 'hybrid',
mapProvider: maplibreProvider(),
mapStyle: {
url: 'https://your-tile-url/style.json',
attribution: 'Your tile attribution'
},
center: [-0.1276, 51.5074],
zoom: 12,
containerHeight: '516px',
plugins: [interactPlugin],
// Back and Continue buttons shown inside the map when fullscreen (mobile)
backAndContinue: {
backLabel: 'Back',
continueLabel: 'Continue',
continueEnabledWhen: ({ mapState }) =>
mapState.markers.items.some(m => m.id === 'location')
}
})
map.on('map:ready', () => {
interactPlugin.enable()
})
// Fired when the built-in Continue button is clicked (mobile/fullscreen)
map.on('app:continue', ({ mapState }) => {
const marker = mapState.markers.items.find(m => m.id === 'location')
// navigate to next step with marker.coords
})
// --- External Continue button for inline (tablet/desktop) ---
const continueBtn = document.getElementById('continue-btn')
const externalButtons = document.getElementById('external-buttons')
// Show/hide external buttons based on whether the map is inline or fullscreen.
// app:opened fires on first load and when the map is shown after being hidden.
// app:fullscreenchange fires when the viewport resizes while the map is already visible.
const setInline = (isFullscreen) => {
externalButtons.hidden = isFullscreen
}
map.on('app:opened', ({ isFullscreen }) => { setInline(isFullscreen) })
map.on('app:closed', () => { externalButtons.hidden = true })
map.on('app:fullscreenchange', ({ isFullscreen }) => { setInline(isFullscreen) })
map.on('interact:markerchange', () => {
continueBtn.disabled = false
})
continueBtn.addEventListener('click', () => {
// navigate to next step
})