Tech: Angular + Esri Series — Map View

A Complete Guide to Building an Interactive Map with Angular

Khoi Bui
4 min readDec 22, 2021

Do you need to integrate an interactive map into your Angular apps ? Are you struggling to find a map library that is easy to use and cost-effective ? If you answer yes to either question you come to the right place. This series will walk you through all the steps to integrate a map library called Esri, a web-based mapping software that gives developer easy access to variety of resources in order to build attractive and high performance maps.

In the first article of this series, our goal is to install and render a simple 2D map into our Angular app.

Install and Set up

Install the packages via npm:

npm install @arcgis/core

Add a map theme:

// styles.scss@import url('~@arcgis/core/assets/esri/themes/light/main.css');

Before We Start Coding…

💡 Go to node_modules/@arcgis/core/assets/esri/themes for more built-in themes provided by Esri.

💡 There are two ways to import ArcGIS modules into our app: AMD and ES. In this series, we’ll be importing all modules as ES modules. For example:

import Map from "@arcgis/core/Map";

💡 For type declaration, use this namespace __esri. For example:

mapView: __esri.MapView;

💡 The API documentation for JavaScript can be found here.

Create Base Map Component

First, we need to create a separate map component to abstract some logic from presentation layer.

Map API

Map API is a component-level service which provides a set of global property and public methods for presentation layer. This API stores an instance of MapView object and two public methods: initMap() and removeMapViewContainer().

// esri-map-api.tsimport { Injectable } from '@angular/core';
import Map from '@arcgis/core/Map';
import MapView from '@arcgis/core/views/MapView';
@Injectable()
export class EsriMapApi {

mapView: __esri.MapView;

constructor() {}
initMap(config: { container: HTMLDivElement }): __esri.MapView {
const map = new Map({
basemap: 'dark-gray-vector',
});

const view = new MapView({
map,
container: config.container,
center: [-98.5, 38.5],
zoom: 3,
});
this.mapView = view; return this.mapView;
}
removeMapViewContainer() {
if (this.mapView) {
this.mapView.destroy();
}
}
}
  • mapView: a 2D map object used to render the map.
  • initMap(); a method that accepts a Map instance and a map container aka DOM element to create a mapView object.
  • removeMapViewContainer(): a method that destroys a mapView instance when it’s no longer used.

Map Component

  1. Map component is responsible for rendering the map.
  • The component injects a new instance of Map API and obtains map container in the template.
  • The component also calls two public methods from Map API to create and destroy the map instance.
  • After the map is created it will emit an event back to presentation layer with the instance of Map API.
// esri-map.component.tsimport { Component, ElementRef, EventEmitter, OnDestroy, OnInit, Output, ViewChild } from '@angular/core';
import { EsriMapApi } from './esri-map-api';
@Component({
selector: 'app-esri-map',
templateUrl: './esri-map.component.html',
styleUrls: ['./esri-map.component.css'],
providers: [EsriMapApi]
})
export class EsriMapComponent implements OnInit, OnDestroy {
@ViewChild('mapViewNode', { static: true })
private mapViewEl: ElementRef;
@Output()
mapReady = new EventEmitter();
constructor(private mapApi: EsriMapApi) {} initMap() {
const view = this.mapApi.initMap({
container: this.mapViewEl.nativeElement,
});
return view.when();
}
ngOnInit() {
this.initMap().then(() => {
this.mapReady.emit(this.mapApi);
});
}
ngOnDestroy(): void {
this.mapApi.removeMapViewContainer();
}
}

2. Below is the map template which declares a DOM element for map container.

// esri-map.component.html<div #mapViewNode style="width: 100%; height: 100%"></div>

3. Declare and export map component in a module.

// esri-map.module.tsimport { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { EsriMapComponent } from './esri-map.component';
@NgModule({
imports: [CommonModule],
declarations: [EsriMapComponent],
exports: [EsriMapComponent],
})
export class EsriMapModule {}

Presentation Layer

Finally we need to create a presentation layer which consumes the map component created in previous section.

Here’s the template for presentation layer. Note that a height must be declared for the map to render correctly.

// app.component.html<div style="height: calc(100vh - 20px)">
<app-esri-map (mapReady)="onMapReady($event)"></app-esri-map>
</div>

The component for presentation layer should have a callback method to obtain the Map API instance from Map component. This instance provides access to the mapView object which can be used to add map features and handle interaction between the user and the map.

// app.component.tsimport { Component } from '@angular/core';
import { EsriMapApi } from './esri-map/esri-map-api';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {

mapApi: EsriMapApi;
onMapReady(mapApi: EsriMapApi) {
this.mapApi = mapApi;
}
}

Congratulations for reaching to this point. Your map should be rendered like the screenshot below. See full demo here.

Esri Map

We will be adding more exciting features to the map in the next articles. Stay tuned.

--

--

Khoi Bui

Front End architect, opensource contributor and investment enthusiast. New content posted every week.