Search code examples
angulartypescriptangular7esri

ESRI loader search widget focus out issue with angular 7


I have to implement an ESRI map using esri-loader in angular application. everything working fine but if we type something in search widget then on focus out of search widget it throwing the following error

"Uncaught TypeError: Cannot read property 'parentNode' of null
    at HTMLInputElement.d (dojo.js:2209)
    at Object.trigger (jquery.min.js:2)
    at Object.simulate (jquery.min.js:2)
    at HTMLDocument.n (jquery.min.js:2)
    at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:423)
    at Zone.push../node_modules/zone.js/dist/zone.js.Zone.runTask (zone.js:195)
    at ZoneTask.push../node_modules/zone.js/dist/zone.js.ZoneTask.invokeTask [as invoke] (zone.js:498)
    at invokeTask (zone.js:1693)
    at HTMLDocument.globalZoneAwareCaptureCallback (zone.js:1762)

I am using 4.14 version of esri

I have refer this but not able to resolve.

package.json:

"esri-loader": "^2.15.0"

code:

import { Component, OnInit, OnDestroy, ViewChild, ElementRef } from "@angular/core";
import { loadModules ,loadScript} from "esri-loader";    
@Component({
    selector: "app-esri-map",
    template: `
  <span> map component workes</span>
  <div class="esri-view" #mapViewNode></div>
  `,
    styles: [`
    @import url('https://js.arcgis.com/4.14/esri/css/main.css');    
    .esri-view {
      height: 600px;
    }`
    ]
})
export class MapComponent implements OnInit, OnDestroy {
    // The <div> where we will place the map
    @ViewChild("mapViewNode", { static: true }) private mapViewEl: ElementRef;
    view: any;    
    constructor() {
         loadScript();
     }    
    async initializeMap() {
        try {
           
            // Load the modules for the ArcGIS API for JavaScript
            const options = { version: '4.14', css: true };
          
            const [Map, MapView, Search] = await loadModules(
                ["esri/Map",
                    "esri/views/MapView",
                    "esri/widgets/Search"],options);

            // Configure the Map
            const mapProperties = {
                basemap: "streets"
            };

            const map = new Map(mapProperties);

            // Initialize the MapView
            const mapViewProperties = {
                container: this.mapViewEl.nativeElement,
                zoom: 10,
                map: map
            };

            this.view = new MapView(mapViewProperties);
            var search = new Search({
                view: this.view,
                searchTerm: `15 Inverness Way East, Englewood, CO80112, United States`,
            });
            console.log('search', search.search());
            this.view.ui.add(search, "top-right");
            search.on("select-result", function (event) {
                console.log("The selected search result: ", event);
                console.log('attributes', event.result.feature.attributes)
            });
            await this.view.when(); // wait for map to load
            console.log('this.view', this.view);
            return this.view;
        } catch (error) {
            console.error("EsriLoader: ", error);
        }
    }

    ngOnInit() {
        this.initializeMap();
    }
    ngAfterViewInit() {

    }

    ngOnDestroy() {
        if (this.view) {
            // destroy the map view
            this.view.container = null;
        }
    }
}

do I need to change some configuration? please suggest me.


Solution

  • add following code to the initializeMap() so we can explicitly set on focus out as null

    const handler = search.on('search-focus', event => {
                    handler.remove();
                    const input = document.querySelector('.esri-search__input') as any
                    if (input) {
                        input.onfocusout = null;
                    }
                });
    

    full code block

     import { Component, OnInit, OnDestroy, ViewChild, ElementRef, Input, Output, EventEmitter } from "@angular/core";
        import { loadModules, loadScript } from "esri-loader";
        @Component({
            selector: "app-esri-map",
            template: `
          <div class="esri-view" #mapViewNode></div>
          `,
            styles: [`
         /* @import url('https://js.arcgis.com/4.14/esri/css/main.css'); */
            .esri-view {
              height: 400px;
            }`
            ]
        })
        export class MapComponent implements OnInit, OnDestroy {
            // The <div> where we will place the map
            @ViewChild("mapViewNode", { static: true }) private mapViewEl: ElementRef;
            view: any;
            @Input() searchString: string;
            @Output() notifyAttributes: EventEmitter<any> = new EventEmitter();
            constructor() {
                //   loadScript();
                //"esri-loader": "^2.15.0", in dependency section.
            }
            async initializeMap() {
                try {
                    // Load the modules for the ArcGIS API for JavaScript
                    const options = { version: '4.14', css: true };
                    const [Map, MapView, Search] = await loadModules(
                        ["esri/Map",
                            "esri/views/MapView",
                            "esri/widgets/Search"], options);
                    // Configure the Map
                    const mapProperties = {
                        basemap: "streets"
                    };
                    const map = new Map(mapProperties);
                    // Initialize the MapView
                    const mapViewProperties = {
                        container: this.mapViewEl.nativeElement,
                        zoom: 2,
                        center: [0.0000, 45.00000],
                        map: map
                    };
                    this.view = new MapView(mapViewProperties);
                    var search = new Search({
                        view: this.view,
                        searchTerm: this.searchString,
                    });
                    if (this.searchString) {
                        search.search();
                    }
                    this.view.ui.add(search, "top-right");
                    const handler = search.on('search-focus', event => {
                        handler.remove();
                        const input = document.querySelector('.esri-search__input') as any
                        if (input) {
                            input.onfocusout = null;
                        }
                    });
                    search.on("select-result", (event) => {
                        this.notifyAttributes.emit(event.result.feature.attributes);
                    });
                    await this.view.when(() => {
                        const input = document.querySelector('.esri-search__input') as any
                        if (input) {
                            input.onfocusout = null;
                        }
                    }); // wait for map to load
                    return this.view;
                } catch (error) {
                    console.error("EsriLoader: ", error);
                }
            }
            ngOnInit() {
                this.initializeMap();
            }
            ngOnDestroy() {
                if (this.view) {
                    this.view.container = null;
                }
            }
        }