Angular 7 ESRI loader search widget focus out bug: finding a solution

I am currently working on implementing an ESRI map using esri-loader in my Angular application. Everything seems to be working fine, but I am encountering an error when typing something into the search widget and then focusing out of it.

"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 version 4.14 of ESRI.

I have looked into this thread for a solution, but haven't been able to resolve it yet.

Here is my package.json:

"esri-loader": "^2.15.0"

For the code implementation, here is what I have:

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 you think there is a need to change some configuration? Any suggestions would be greatly appreciated.

Answer №1

Insert the code snippet below into the initializeMap() function to 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;
                }
            });

Here is the 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;
            }
        }
    }

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Ensure that the form is submitted only after confirming it in the modal with react-hook-form

**I am facing an issue with submitting react-hook-form on confirm in a modal component. Whenever the user selects confirm, I need the form to be submitted directly. I have tried writing the modal inside FormSubmitButton. Also, I have tried placing it insi ...

Mapping nested values from a Typescript object to properties of a JSON object

Within the scope of a current project I am involved in, we have opted for utilizing the Angular toolset identified as formly to dynamically generate our forms. The present configuration of the form is hardcoded into a Typescript object denoted as mockForm ...

Values within the inner *ngFor loop have been selected from the outer *ngFor loop

In our Angular 4 application, we are facing a specific requirement that needs to be addressed. We have successfully implemented *ngFor up to three levels and below is the code snippet for the implementation: <div *ngFor="let country of Countries"> ...

Exploring the Ways to Determine Array Type in Typescript Generics

I'm working with a method that looks like this: public select(fieldName: keyof TType) In this scenario, TType can potentially be an array type. If fieldName is called with a type of User[], I want to access the properties of User instead of the defa ...

Developing a Javascript object using Typescript

Trying my hand at crafting a TypeScript object from JavaScript. The specific JavaScript object I'm attempting to construct can be found here: https://cdnjs.cloudflare.com/ajax/libs/chess.js/0.10.2/chess.js In the provided JavaScript example, the obj ...

The problem with uploading files in Angular4 (with multer on the server)

In my current project, I encountered an issue where the front end file was not getting transferred to the server side after finishing both the front end and back end logic. Despite spending more than an hour debugging, I couldn't pinpoint the exact ca ...

Running Jenkins in a Docker container to initiate the process of building an Angular application within a

Recently, I began my journey of learning Jenkins and successfully launched it on Docker. Now, I have a project built in Angular along with a Dockerfile created to produce a Docker image. However, when attempting to start the process from Jenkins, an erro ...

The event handler cdkDropListDropped="drop($event)" is not triggering when interacting with a Material table that has a

Currently, I am working on implementing a column drag-and-drop feature using mat-table and cdkDragDrop in Angular (specifically with Angular 8). Here is the progress I have made so far: Within the component.html file: <mat-table cdkDropList cdkDrop ...

The inclusion of an XSRF-TOKEN using an HTTP Interceptor results in a 400 Error Request

Implementing XSRF-TOKEN to enhance security and prevent XSRF attacks as I pass a JWT through a cookie for my Angular application. Below is the structure of my HttpInterceptor. intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEv ...

Angular5 - Modify a public variable using an intercept in a static service

Take into account the following Angular service: @Injectable() export class AuthService { public userConnected: UserManageInfo; getManageInfo(): Observable<UserManageInfo> { return this.httpClient .get('api/Account/Man ...

Ways to parse the data from a response received from an Axios POST request

After sending the same POST request using a cURL command, the response I receive is: {"allowed":[],"error":null} However, when I incorporate the POST request in my code and print it using either console.log("response: ", resp ...

The current issue I am facing is that the option disabled with value="null" selected is not being shown on the screen. Instead, it should display as "Choose User Types"

<select class="form-control" id="ddSelectaTopic" onchange="if(this.value==='') {this.style.color='#999'} else {this.style.color='#333'}" [(ngModel)]="user_type_id" (change)=&q ...

Can you identify the nature of the argument(s) used in a styled-component?

Utilizing typescript and react in this scenario. Fetching my variable const style = 'display: inline-block;' Constructing a simple component export const GitHubIcon = () => <i className="fa-brands fa-github"></i> Enh ...

The spread operator seems to be malfunctioning whenever I incorporate tailwindcss into my code

Hi there! I hope you're doing well! I've come across a strange issue in Tailwindcss. When I close the scope of a component and try to use props like ...rest, the className doesn't function as expected. Here's an example: import { Butto ...

AngularJS and CSS: A Guide to Effortlessly Toggle Sliding List Elements

I am in the process of developing a drop-down menu that can be clicked. Using my custom AngularJS directive, I have successfully implemented functionality to load menu items dynamically. While I have made significant progress, I have encountered a small i ...

Using axiosjs to send FormData from a Node.js environment

I am facing an issue with making the post request correctly using Flightaware's API, which requires form data. Since Node does not support form data, I decided to import form-data from this link. Here is how my code looks like with axios. import { Fl ...

Leverage the exported data from Highcharts Editor to create a fresh React chart

I am currently working on implementing the following workflow Create a chart using the Highcharts Editor tool Export the JSON object from the Editor that represents the chart Utilize the exported JSON to render a new chart After creating a chart through ...

Encountering an issue with Jest when using jest.spyOn() and mockReturnValueOnce causing an error

jest --passWithNoTests --silent --noStackTrace --runInBand --watch -c jest-unit-config.js Project repository An error occurred at jest.spyOn(bcrypt, 'hash').mockRejectedValue(new Error('Async error message')) Error TS2345: The argum ...

Page Breaks - Patience in anticipation of dataSource readiness

I am facing an issue with my pagination service and component. The dataSource appears empty when the page is loaded for the first time, but by the second time it is populated and I can display the dataTable and paginate successfully. Is there a workaround ...

Disarrayed generic parameters in TypeScript

The title of the question may not be perfect, but it's the best I could do. Imagine a scenario where there is a function that accepts a callback along with an optional array. The callback takes an index and another optional array as parameters, and t ...