Skip to content

Angular

View .md

Use the <instant-map> element in a standalone Angular component. Server rendering puts the first image in the HTML, and the element takes over in the browser.

Terminal window
npm install instantmap-js

Define the element before Angular starts. If it is defined later, Angular binds markers to a plain element and the setter never runs.

src/main.ts
import { bootstrapApplication } from '@angular/platform-browser';
import { appConfig } from './app/app.config';
import { App } from './app/app';
import('instantmap-js').then(() => bootstrapApplication(App, appConfig));

Allow the custom element in the component and build the poster URL.

src/app/app.ts
import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import type { Marker } from 'instantmap-js';
import { staticUrl } from 'instantmap-js/server';
import { listings } from './listings';
@Component({
selector: 'app-root',
schemas: [CUSTOM_ELEMENTS_SCHEMA],
templateUrl: './app.html',
styleUrl: './app.css',
})
export class App {
readonly center: [number, number] = [-97.74, 30.27];
readonly zoom = 12;
readonly markers: Marker[] = listings();
readonly poster = staticUrl({
center: this.center,
zoom: this.zoom,
width: 1200,
height: 640,
ratio: 2,
markers: this.markers,
});
}
src/app/app.html
<instant-map
ngSkipHydration
[attr.center]="center.join(',')"
[attr.zoom]="zoom"
[markers]="markers"
>
<img
[src]="poster"
alt="Map of Austin"
width="1200"
height="640"
fetchpriority="high"
style="position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover"
/>
</instant-map>

Size the map in the stylesheet, not with an inline style. Angular rewrites an inline style attribute on the element and removes the variables the map sets on itself.

src/app/app.css
instant-map {
display: block;
position: relative;
height: 520px;
}

Create the app with server rendering and keep the render mode on Server.

src/app/app.routes.server.ts
import { RenderMode, ServerRoute } from '@angular/ssr';
export const serverRoutes: ServerRoute[] = [{ path: '**', renderMode: RenderMode.Server }];

Build, start the server and check the HTML:

Terminal window
ng build
node dist/angular/server/server.mjs
curl -s https://your-site.example/ | grep -o '<img[^>]*static?[^>]*'

You should see an <img> whose src points at /static?.

Listen with (markerclick) and call methods through a template reference. Use a signal for anything the event changes, because a zoneless app does not refresh on a plain property.

src/app/app.ts
import { ElementRef, signal, ViewChild } from '@angular/core';
import type { InstantMapElement } from 'instantmap-js';
export class App {
@ViewChild('map') map?: ElementRef<InstantMapElement>;
opened = signal('Click a price to open its card.');
showDowntown() {
void this.map?.nativeElement.flyTo({ center: [-97.743, 30.267], zoom: 15 });
}
onMarkerClick(event: Event) {
const { marker } = (event as CustomEvent<{ marker: Marker }>).detail;
this.opened.set(`${marker.title}, ${marker.label}`);
}
}
src/app/app.html
<instant-map #map (markerclick)="onMarkerClick($event)" ...></instant-map>
<p>{{ opened() }}</p>
<button type="button" (click)="showDowntown()">Show downtown</button>
  • Starting Angular before import('instantmap-js') finishes. markers is then bound to an undefined element and never reaches the map.
  • Putting style="..." on <instant-map>. Angular overwrites it and removes the theme variables the map sets on itself.
  • Leaving out CUSTOM_ELEMENTS_SCHEMA. Angular rejects the unknown tag.
  • Giving the map no height. It collapses to nothing.
  • Leaving out ngSkipHydration. Hydration then fights the element for its children.
Add an Instant Map to my Angular app with server rendering. Follow https://instantmap.org/docs/frameworks/angular.md exactly. Import instantmap before bootstrapApplication, add CUSTOM_ELEMENTS_SCHEMA, build the poster URL with staticUrl from instantmap-js/server and render it as an img inside instant-map with ngSkipHydration, and size the element in CSS rather than with an inline style. Build, start the server, and confirm the HTML from curl contains an img with /static? in its src.

examples/angular on GitHub