Refreshing Layers on an Angular 10 ESRI Map Without Refreshing the Entire Map

942 views Asked by At

I have created an Esri Map in Angular 10. The user can select the layers on the map from a group button. So the input will be an array eg: ['0','1','2']. The numbers are the map layer number. All these functionalities are working fine, But I have to add the layers without refreshing the entire map. Please find the code below.

import {
  Component,
  OnInit,
  ViewChild,
  ElementRef,
  Input,
  Output,
  EventEmitter,
  OnDestroy,
} from '@angular/core';
import { loadModules } from 'esri-loader';
import esri = __esri; // Esri TypeScript Types
import { empty } from 'rxjs';

@Component({
  selector: 'app-esri-adv-map',
  templateUrl: './esri-adv-map.component.html',
  styleUrls: ['./esri-adv-map.component.css'],
})
export class EsriAdvMapComponent implements OnInit {
  @Output() mapLoadedEvent = new EventEmitter<boolean>();
  @ViewChild('mapViewNode', { static: true }) private mapViewEl: ElementRef;
  view: any;

  private _zoom = 15;
  private _basemap = 'hybrid';
  private _loaded = false;
  private _view: esri.MapView = null;
  private _nextBasemap = 'streets';
  public _selectedLayer: Array<string>;

  public onLayerChange(val: Array<string>) {
    // eg: val = ['0','1','2'];
    this._selectedLayer = val;
    this.ngOnInit();
  }
  constructor() {}

  async initializeMap() {
    try {
      // Load the modules for the ArcGIS API for JavaScript
      const [
        EsriMap,
        EsriMapView,
        FeatureLayer,
        BasemapToggle,
        BasemapGallery,
      ] = await loadModules([
        'esri/Map',
        'esri/views/MapView',
        'esri/layers/FeatureLayer',
        'esri/widgets/BasemapToggle',
        'esri/widgets/BasemapGallery',
      ]);

      // Configure the Map

      const mapProperties: esri.MapProperties = {
        basemap: this._basemap,
      };

      const map: esri.Map = new EsriMap(mapProperties);

      // Initialize the MapView
      const mapViewProperties: esri.MapViewProperties = {
        container: this.mapViewEl.nativeElement,
        center: this._center,
        zoom: this._zoom,
        map: map,
      };

      this._view = new EsriMapView(mapViewProperties);

      // Add layers to the map according to the selection
      let layerArray = this._selectedLayer;
      console.log(layerArray);

      if (typeof layerArray != 'undefined') {
        layerArray.forEach((layer) => {
          const addLayer = new FeatureLayer({
            url:
              'https://gis.dogis.org/arcgis/rest/services/test/MapServer/' +
              layer,
          });
          map.add(addLayer);
        });
      }

      // Basemap toglle section
      var basemapToggle = new BasemapToggle({
        view: this._view,
        nextBasemap: this._nextBasemap,
      });
      this._view.ui.add(basemapToggle, 'top-right');

      await this._view.when();
      return this._view;
    } catch (error) {
      console.log('EsriLoader: ', error);
    }
  }

  ngOnInit(): void {
    this.initializeMap().then((mapView) => {
      console.log('mapView ready: ', this._view.ready);
      this._loaded = this._view.ready;
      this.mapLoadedEvent.emit(true);
    });
  }
}

The function 'onLayerChange()' is from the group button. Once the event is triggered then calling the 'ngOnInit()' which loads the map with the selected layers. But how can we load only layers, not the entire map? Thanks.

1

There are 1 answers

5
cabesuon On BEST ANSWER

There is no need to "re-initialize" the component.

I think the simple solution is to create all layers, add it to map, and then just play with the visible property of the layers.

As an example, let say you keep your layer indexes in layerMapIdxArray (the indexes of the possible feature layers). Lets add a dictionary layersDic with the possible layers and initialize them.

layersMapIdxArray: number[] = ['0', '1', '4', '3', '8', '7']; // example
layersDic = {};
initLayersDic () {
  for (const idx of layersMapIdxArray) {
    this.layersDic[idx] = new FeatureLayer({
      url: `https://gis.dogis.org/arcgis/rest/services/test/MapServer/${idx}`,
      visible: false // <- with this starts off
    });
    map.add(this.layersDic[idx]);
  }
}

Then in your button group click ( I am guessing ) event handler, just update the visible property accordly.

public onLayerChange(val: Array<string>) {
  // eg: val = ['0','1','2'];
  
  this.visibleFalseAllLayer(); // here you reset the layers visibility
  
  // now turn on the selected layers
  for (const v of val) {
    this.layersDic[idx].visible = true;
  }
}

That's it!.

Btw, the code is an example to express the logic, I did not compile it.