Appearance
Customize Entity Popups with HTML
By default the Mapsted Maps JavaScript API renders a built-in popup when an entity is selected — showing the entity name, category icon, and description from the property data. This guide explains how to replace that popup with your own HTML by supplying an html string on each MapEntity, and how to react to entity-selection events.
Prerequisites
- The library initialized and in the
READYstate (API lifecycle) - Basic familiarity with Select an entity programmatically
How custom popup HTML works
The API does not accept a popupTemplate callback at init(). Instead, each MapEntity object carries an optional html field:
ts
html?: string;The string is injected into the API-hosted iframe's popup layer when that entity is selected. Supply it via one of three methods:
| Method | When to use |
|---|---|
setEntityData(entities) | Bulk-set HTML for many entities at once |
setEntityDataById(id, entity) | Update a single entity by ID |
setEntityDefaults(defaults) | Provide a fallback template applied to every entity that has no per-entity override |
All three accept the same MapEntity shape. The html field is optional; omitting it on a given entity leaves the built-in popup in place for that entity.
Supplying custom HTML per entity
CDN
html
<script src="https://mapi.mapsted.com/v4.0.1/maps.js?id=1234"></script>
<script>
await mapsted.maps.init({ element: '#map' });
// Override the popup for entity 42 in building 7.
await mapsted.maps.setEntityDataById(42, {
id: 42,
buildingId: 7,
html: '<div class="my-popup"><h3>Coffee Shop</h3><p>Open 8 am – 8 pm</p></div>',
});
</script>npm
js
import * as maps from '@mapsted/maps-js-api';
await maps.init({
element: '#map',
propertyId: 1234,
});
// Override the popup for entity 42 in building 7.
await maps.setEntityDataById(42, {
id: 42,
buildingId: 7,
html: '<div class="my-popup"><h3>Coffee Shop</h3><p>Open 8 am – 8 pm</p></div>',
});setEntityDataById validates both the id and entity parameters and throws MAPSTED-1061 if entity is not a plain object
Applying a fallback template to all entities
Use setEntityDefaults to set a single MapEntity object whose fields (including html) are applied to every entity that has no per-entity override. This is the closest equivalent to a global popup template.
CDN
html
<script src="https://mapi.mapsted.com/v4.0.1/maps.js?id=1234"></script>
<script>
await mapsted.maps.init({ element: '#map' });
await mapsted.maps.setEntityDefaults({
id: 0, // id field is required by MapEntity; use 0 for the defaults object
html: '<div class="my-popup"><p>No additional info available.</p></div>',
});
</script>npm
js
import * as maps from '@mapsted/maps-js-api';
await maps.init({
element: '#map',
propertyId: 1234,
});
await maps.setEntityDefaults({
id: 0,
html: '<div class="my-popup"><p>No additional info available.</p></div>',
});setEntityDefaults validates that defaults is a plain MapEntity object and throws MAPSTED-1061 otherwise
Bulk-setting HTML for multiple entities
setEntityData accepts an array of MapEntity objects. Supply the html field on any entry to override its popup.
CDN
html
<script src="https://mapi.mapsted.com/v4.0.1/maps.js?id=1234"></script>
<script>
await mapsted.maps.init({ element: '#map' });
await mapsted.maps.setEntityData([
{
id: 42,
buildingId: 7,
html: '<div class="my-popup"><h3>Coffee Shop</h3></div>',
},
{
id: 87,
buildingId: 7,
html: '<div class="my-popup"><h3>Bookstore</h3></div>',
},
]);
</script>npm
js
import * as maps from '@mapsted/maps-js-api';
await maps.init({
element: '#map',
propertyId: 1234,
});
await maps.setEntityData([
{ id: 42, buildingId: 7, html: '<div class="my-popup"><h3>Coffee Shop</h3></div>' },
{ id: 87, buildingId: 7, html: '<div class="my-popup"><h3>Bookstore</h3></div>' },
]);setEntityData throws MAPSTED-1013 if the argument is not an array
Programmatically opening a popup
Use showPopup(entityId) to open the popup for a specific entity without requiring a user tap and without moving the camera or switching floors. This is the primary API for programmatic popup triggering.
CDN
html
<script src="https://mapi.mapsted.com/v4.0.1/maps.js?id=1234"></script>
<script>
await mapsted.maps.init({ element: '#map' });
// Open the default popup for entity 42.
await mapsted.maps.showPopup(42);
// Open the popup with a custom HTML override for this call.
await mapsted.maps.showPopup(42, {
html: '<div class="my-popup"><h3>Coffee Shop</h3><p>Open 8 am – 8 pm</p></div>',
});
</script>npm
js
import * as maps from '@mapsted/maps-js-api';
await maps.init({
element: '#map',
propertyId: 1234,
});
// Open the default popup for entity 42 (camera stays put, floor unchanged).
await maps.showPopup(42);
// Provide inline HTML — equivalent to setEntityDataById + selectEntity in one round-trip.
await maps.showPopup(42, {
html: '<div class="my-popup"><h3>Coffee Shop</h3><p>Open 8 am – 8 pm</p></div>',
});showPopup throws:
| Error code | Condition |
|---|---|
MAPSTED-1090 | API is not yet in READY state |
MAPSTED-1012 | entityId is null or undefined |
MAPSTED-1013 | entityId is not a string or number |
Tip: To open a popup and pan to the entity, call
selectEntity(entityId)instead.showPopupis for cases where you want the popup to appear without disturbing the user's current map view.
Reacting to entity selection
Two events fire when an entity is selected. Both are typed in KnownEventPayload with an EntityData payload ({ buildingId, floorId, entityId }):
| Event | Fires |
|---|---|
select | When any entity is selected on the map |
detailsView | When the details popup is opened for an entity |
CDN
html
<script src="https://mapi.mapsted.com/v4.0.1/maps.js?id=1234"></script>
<script>
await mapsted.maps.init({ element: '#map' });
mapsted.maps.on('detailsView', ({ entityId, buildingId, floorId }) => {
console.log('Details opened for entity', entityId, 'in building', buildingId);
// Render your own sidebar or panel here using entityId.
});
</script>npm
js
import * as maps from '@mapsted/maps-js-api';
await maps.init({
element: '#map',
propertyId: 1234,
});
maps.on('detailsView', ({ entityId, buildingId, floorId }) => {
console.log('Details opened for entity', entityId, 'in building', buildingId);
});Disabling the built-in popup entirely
To suppress the default popup without providing per-entity HTML — for example when you render a custom sidebar — set the defaultPopup feature flag to false. defaultPopup is defined in FeatureFlagSet:
CDN
html
<script src="https://mapi.mapsted.com/v4.0.1/maps.js?id=1234"></script>
<script>
await mapsted.maps.init({ element: '#map' });
await mapsted.maps.setFeatureFlags({ defaultPopup: false });
mapsted.maps.on('select', ({ entityId, buildingId, floorId }) => {
renderMySidebar({ entityId, buildingId, floorId }); // your own UI
});
</script>npm
js
import * as maps from '@mapsted/maps-js-api';
await maps.init({
element: '#map',
propertyId: 1234,
});
await maps.setFeatureFlags({ defaultPopup: false });
maps.on('select', ({ entityId, buildingId, floorId }) => {
renderMySidebar({ entityId, buildingId, floorId });
});See the feature flags guide for the full setFeatureFlags reference.
Current public-API scope note
data-mapsted-trigger / data-mapsted-event / data-mapsted-payload inline attributes are NOT part of the public JS API surface. These attributes are an internal escape-hatch mechanism processed inside the map iframe, not by the JS API layer. They are treated as CMS-controlled and untrusted. Consumer code must not rely on these attributes firing events on the JS API emitter — there is no popupAction event in KNOWN_EVENTS.
To react to user interactions inside an html popup, attach DOM event listeners to elements rendered in your own external UI (sidebar, modal), or use maps.on('select', …) / maps.on('detailsView', …) to detect entity selection and build your own interaction surface outside the iframe.
No built-in popup-button callback: The API provides no mechanism for popup buttons inside the
htmlstring to call back into the host page without custom DOM event handling. Ifdata-mapsted-trigger/data-mapsted-eventcallback support is needed (a named event fired on themapsemitter when adata-mapsted-triggerelement is clicked), contact info@mapsted.com to request this as a future addition — it does not exist today.