3

I am looking at ArcGIS Javascript API 4.18.1. But it is confusing, how I should add it to a new Angular 11 project. Is there an example project somewhere that shows the basic folder structure and getting a map setup in Angular 11? I want to get it set up with just ES modules using NPM.

https://developers.arcgis.com/javascript/latest/es-modules/

I did this:

npm install @arcgis/core

Then I added the following to app.component.ts

import WebMap from '@arcgis/core/WebMap';
import MapView from '@arcgis/core/views/MapView';

I am new to this. And It seems like all the documentation talks about React.

Then in the getting started with Map it has you enter a key:

<html>
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no" />
    <title>ArcGIS API for JavaScript Tutorials: Display a map</title>

    <style>
      html,
      body,
      #viewDiv {
        padding: 0;
        margin: 0;
        height: 100%;
        width: 100%;
      }
    </style>

    <link rel="stylesheet" href="https://js.arcgis.com/4.18/esri/themes/light/main.css">
    <script src="https://js.arcgis.com/4.18/"></script>

    <script>
      require(["esri/config","esri/Map", "esri/views/MapView"], function (esriConfig,Map, MapView) {

        esriConfig.apiKey = "YOUR-API-KEY";

        const map = new Map({
          basemap: "arcgis-topographic" // Basemap layer service
        });

      });
    </script>

  </head>
  <body>
    <div id="viewDiv"></div>
  </body>
</html>

But these docs are not for Typescript. Do they have typescript docs somewhere? How do you add the Key with the new API 4.18.1 and Typescript and NPM and Angular 11?

Crimson_Hawk
  • 133
  • 1
  • 2
  • 10
  • Dont you have to configure the key in this line? esriConfig.apiKey = "YOUR-API-KEY"; Or what exactly is the question? – Tigerware Jan 29 '21 at 18:22
  • Yes, but in typescript where do you do that? The new docs don't show an example. I imagine that it would be different with the new API and Typescript that Esri has been working on. I just don't see how to do it. So my question is how do you do the example above with the key in Typescript. – Crimson_Hawk Jan 29 '21 at 18:25
  • Well but you are using HTML + some JavaScript right now. Other than that you might want to create a typescript file to use. Maybe the typescript documentation helps. – Tigerware Jan 29 '21 at 19:56
  • BluE do you have a link or something that points to an example, like the example above. That will do the same thing but in typescript? I cant find a simple example. – Crimson_Hawk Feb 01 '21 at 18:58
  • Nothing specific to typescript and arcgis. Maybe you can seperate those concerns? I would try to get the basics working with javascript and then convert the code to typescript. – Tigerware Feb 01 '21 at 20:24
  • 2
    Are you getting any errors to work off of? With the ES modules you also need to copy the library to an `assets` directory https://developers.arcgis.com/javascript/latest/es-modules/#copy-assets . Angular CLI has was to do this https://stackoverflow.com/questions/40567449/using-angular-cli-build-to-copy-a-file-directory I believe. – Carson Wood Feb 02 '21 at 21:26
  • @BluE I will try to do the conversion myself. I was trying to see if anyone in the community had an example. or knew of one. – Crimson_Hawk Feb 03 '21 at 03:49
  • Carson Wood - Those are helpful links. I will try to get an example working. And then post it here. Thank you! – Crimson_Hawk Feb 03 '21 at 03:50

1 Answers1

2

This is what I came up with.

It is based off https://github.com/TheKeithStewart/angular-esri-components which uses the arcgis-js-api library

https://github.com/Esri/jsapi-resources/tree/master/esm-samples/jsapi-angular-cli has the basic setup instructions for using @arcgis/core in an Angular application

esri-map.component.scss:

#mapViewNode {
  padding: 0;
  margin: 0;
  height: 100%;
  width: 100%;
}

esri-map.component.ts:

import {
  Component,
  ElementRef,
  Input,
  OnInit,
  NgZone,
  OnDestroy,
  ViewChild,
  Output,
  EventEmitter,
} from '@angular/core';
import config from '@arcgis/core/config';
import { EsriMapService } from './esri-map.service';

@Component({
  // tslint:disable-next-line: component-selector
  selector: 'esri-map',
  template: '<div #mapViewNode></div>',
  styleUrls: ['./esri-map.component.scss'],
})
  export class EsriMapComponent implements OnInit, OnDestroy {
    @ViewChild('mapViewNode', { static: true }) private elementRef!: ElementRef;
    @Input() mapProperties!: any;
    @Input() mapViewProperties!: any;
    @Output() mapInit: EventEmitter<any> = new EventEmitter();

    private mapView: any;

  constructor(private zone: NgZone, private mapService: EsriMapService) {}

  ngOnInit(): void {
    config.assetsPath = 'assets/';
    this.zone.runOutsideAngular(() => {
      this.loadMap();
    });
  }

  ngOnDestroy(): void {
    this.mapView.destroy();
  }

  loadMap(): void {
    this.mapService.isLoaded.subscribe((n: any) => {
      this.mapView = n.view;
      this.zone.run(() => {
        this.mapInit.emit({ map: n.map, view: n.view });
        this.mapInit.complete();
      });
    });
    this.mapService.loadWebMap({
      ...this.mapProperties,
      ...this.mapViewProperties,
      container: this.elementRef.nativeElement,
    });


  }

esri-map.service.ts:

import { EventEmitter, Injectable } from '@angular/core';
import MapView from '@arcgis/core/views/MapView';
import WebMap from '@arcgis/core/WebMap';
import Widget from '@arcgis/core/widgets/Widget';
import Layer from '@arcgis/core/layers/Layer';

export type Position =
  | 'bottom-leading'
  | 'bottom-left'
  | 'bottom-right'
  | 'bottom-trailing'
  | 'top-leading'
  | 'top-left'
  | 'top-right'
  | 'top-trailing'
  | 'manual';
@Injectable({
  providedIn: 'root',
})
export class EsriMapService {
  map!: WebMap;
  view!: MapView;
  loaded = false;
  isLoaded = new EventEmitter();

  constructor() {}

  loadWebMap(props: {
    basemap: any;
    container: any;
    center: any;
    zoom: any;
  }): void {
    this.map = new WebMap({ basemap: props.basemap });
    this.view = new MapView({
      container: props.container,
      map: this.map,
      center: props.center,
      zoom: props.zoom,
    });
    this.loaded = true;
    this.isLoaded.emit({
      map: this.map,
      view: this.view,
    });
  }

  addLayer(layer: Layer, clearLayers?: boolean): void {
    if (clearLayers) {
      this.view.map.removeAll();
    }
    this.view.map.add(layer);
  }

  addWidget(
    component: string | HTMLElement | Widget | any[],
    position?: Position,
  ): void {
    this.view.ui.add(component, position);
  }
}

You would just instantiate the component like this:

<esri-map [mapProperties]="mapProperties" [mapViewProperties]="mapViewProperties" (mapInit)="onMapInit($event)">
</esri-map>

mapProperties sets the base map.

mapViewProperties sets the center and zoom.

mapInit lets you know when the map is loaded.

The service provides the map view for constructing the map.

You would then add your layers to the map view as usual.

Bill Clyde
  • 220
  • 5
  • 8
  • Where do you add the API-KEY? That is another part that I am confused about. And you added a service! Thank you. Great Answer! Very straightforward. – Crimson_Hawk Feb 19 '21 at 19:54
  • esriConfig.apiKey = "YOUR-API-KEY"; – Crimson_Hawk Feb 19 '21 at 20:01
  • config.assetsPath = 'assets/'; Would I add it to this? config.apiKey. Ok, I will play around with that. I am a noob at this. – Crimson_Hawk Feb 19 '21 at 20:02
  • 1
    config.assetsPath is the folder where you copied the esri assets. https://github.com/Esri/jsapi-resources/tree/master/esm-samples/jsapi-angular-cli has the instructions on how to do a basic setup of the api – Bill Clyde Feb 23 '21 at 17:10