Search code examples
javascriptangulararcgis-js-apiesri-maps

ArcGIS Esri - Popup template custom content not showing graphic attributes. (Angular 11)


I'm going to display a customContent in arcgis popup template in Angular 11 application. But the value of graphic.attributes is not coming to the innerText. In console log I can see the graphic objects are coming as expected. But it's showing undefined for grahpic.attributes Can anyone help with to solve this issue?

            new CustomContent({
    outFields: ["*"],
    creator: (eventOrGraphic) => {
        const graphic = eventOrGraphic instanceof Graphic ? eventOrGraphic : eventOrGraphic.graphic;
        const a = document.createElement("a");
        a.href = graphic.attributes.url;
        a.target = "_blank";
        a.innerText = graphic.attributes.url;
        return a;
    }
})

Console.log(eventOrGraphic)

graphic: p
destroy: ƒ value()
initialize: ƒ value()
uid: 1474
__accessor__: g {host: p, properties: Map(8), ctorArgs: null, destroyed: false, lifecycle: 2, …}
attributes: (...)    
geometry: (...)
isAggregate: (...)
layer: (...)
popupTemplate: (...)
sourceLayer: (...)
symbol: (...)
visible: (...)
[[Prototype]]: Object

Console.log(graphic.attributes) - undefined

arcgis-js-api(4.2.1)


Solution

  • Ok, so it seems that the parameter of CustomContent creator function is of the form {graphic: Graphic}.

    The never error is because not type was assigned, so you can assign any to actually avoid it. I am not exactly sure of the correct type.

    This is the key part of the example,

    new CustomContent({
      outFields: ["*"],
      creator: (event: any) => {
        console.log(event.graphic);
        const a = document.createElement("a");
        a.href = event.graphic.attributes.url;
        a.target = "_blank";
        a.innerText = event.graphic.attributes.url;
        console.log(event.graphic.attributes.url);
        return a;
      }
    })
    

    This is the whole example,

    app.component.ts

    import {
      Component,
      OnInit,
      OnDestroy,
      ElementRef,
      ViewChild
    } from '@angular/core';
    
    import ArcGISMap from '@arcgis/core/Map';
    import Graphic from '@arcgis/core/Graphic';
    import MapView from '@arcgis/core/views/MapView';
    import FeatureLayer from '@arcgis/core/layers/FeatureLayer';
    import Collection from "@arcgis/core/core/Collection";
    import CustomContent from '@arcgis/core/popup/content/CustomContent';
    import PopupTemplate from '@arcgis/core/PopupTemplate';
    import SimpleRenderer from "@arcgis/core/renderers/SimpleRenderer";
    import TextSymbol from "@arcgis/core/symbols/TextSymbol";
    @Component({
      selector: 'app-root',
      templateUrl: './app.component.html',
      styleUrls: ['./app.component.scss']
    })
    export class AppComponent implements OnInit, OnDestroy {
      @ViewChild('mapViewNode', { static: true }) private mapViewEl!: ElementRef;
      public view: any = null;
    
      initializeMap(): Promise<any> {
        const container = this.mapViewEl.nativeElement;
    
        const map = new ArcGISMap({
          basemap: "streets-navigation-vector"
        });
    
        const view = new MapView({
          container: container,
          map: map,
          zoom: 12,
          center: { type: 'point', x: -117.1490, y: 32.7353 }
        });
    
        const popupTemplate = new PopupTemplate({
          title: "{name}",
          content: [
            {
              type: "fields",
              fieldInfos: [
                {
                  fieldName: "addrs",
                  label: "Address"
                },
                {
                  fieldName: "lat",
                  label: "Latitude",
                  format: {
                    places: 2
                  }
                },
                {
                  fieldName: "lon",
                  label: "Longitude",
                  format: {
                    places: 2
                  }
                }
              ]
            },
            new CustomContent({
              outFields: ["*"],
              creator: (event: any) => {
                console.log(event.graphic);
                const a = document.createElement("a");
                a.href = event.graphic.attributes.url;
                a.target = "_blank";
                a.innerText = event.graphic.attributes.url;
                console.log(event.graphic.attributes.url);
                return a;
              }
            })
          ],
          outFields: ["*"]
        });
        const data = [
          {
            lat: 32.727482,
            lon: -117.1560632,
            name: "Automotive Museum",
            addrs: "2080 Pan American Plaza, San Diego, CA 92101, United States",
            url: "http://sdautomuseum.org/"
          },
          {
            lat: 32.7136902,
            lon: -117.1763293,
            name: "USS Midway Museum",
            addrs: "910 N Harbor Dr, San Diego, CA 92101, United States",
            url: "http://www.midway.org/"
          },
          {
            lat: 32.7641112,
            lon: -117.2284536,
            name: "SeaWorld",
            addrs: "500 Sea World Dr, San Diego, CA 92109, United States",
            url: "https://seaworld.com/san-diego"
          },
          {
            lat: 32.7360032,
            lon: -117.1557741,
            name: "Zoo",
            addrs: "2920 Zoo Dr, San Diego, CA 92101, United States",
            url: "https://zoo.sandiegozoo.org/"
          }
        ];
        const layer = new FeatureLayer({
          source: new Collection(data.map((d, i) => (
            {
              geometry: {
                type: "point",
                longitude: d.lon,
                latitude: d.lat
              },
              attributes: {
                ObjectID: i,
                ...d
              }
            }
          ))),
          fields: [
            {
              name: "ObjectID",
              alias: "ObjectID",
              type: "oid"
            },
            {
              name: "name",
              alias: "Name",
              type: "string"
            },
            {
              name: "addrs",
              alias: "addrs",
              type: "string"
            },
            {
              name: "url",
              alias: "url",
              type: "string"
            },
            {
              name: "lat",
              alias: "Latitude",
              type: "double"
            },
            {
              name: "lon",
              alias: "Longitude",
              type: "double"
            },
          ],
          objectIdField: "ObjectID",
          geometryType: "point",
          renderer: new SimpleRenderer({
            symbol: new TextSymbol({
              color: "red",
              text: "\ue61d",
              font: {
                size: 30,
                family: "CalciteWebCoreIcons"
              }
            })
          }),
          popupTemplate
        });
    
        map.add(layer);
        this.view = view;
        return this.view.when();
      }
    
      ngOnInit(): any {
        this.initializeMap().then(() => {
          console.log('The map is ready.');
        });
      }
    
      ngOnDestroy(): void {
        if (this.view) {
          this.view.destroy();
        }
      }
    }
    

    app.component.html

    <div #mapViewNode></div>
    

    app.component.scss

    @import 'https://js.arcgis.com/4.22/@arcgis/core/assets/esri/themes/light/main.css';
    .esri-view {
      padding: 0;
      margin: 0;
      height: 100%;
      width: 100%;
    }
    #mapViewNode {
      padding: 0;
      margin: 0;
      height: 100%;
      width: 100%;
    }
    

    styles.scss

    html,
    body {
      padding: 0;
      margin: 0;
      height: 100%;
      width: 100%;
    }