The modal dialog from angular/material is unable to function properly when a shape on Google Maps is clicked

I have incorporated Google Maps into my application in order to showcase shapes (polygons/circles) and markers. To interact with Google Maps in Angular, I am utilizing the type definition "npm install --save @types/googlemaps". Upon clicking a shape, I need to open a modal dialog. Here is the code snippet I've written to achieve this:

google.maps.event.addListener(shape, 'click', (event) => {
        let customData = shape.CustomData;

        this.config.data =
            {
                companyId: this.companyId,
                siteId: customData.SiteId,
                siteName: customData.SiteName
            };
        this.dialog.open(SiteFloorDetailsComponent, this.config);

    });

The modal popup opens successfully and the constructor of SiteFloorDetailsComponent is invoked. However, the ngOnInit function within SiteFloorDetailsComponent is not triggered, resulting in dynamic data and contents not loading. Furthermore, when attempting to close the modal popup using the close button, the close event within SiteFloorDetailsComponent is fired but the modal does not close. No errors are displayed in the console. When I move the modal opening code out of the shape click event handler as shown below, the functionality works as expected:

 this.config.data =
        {
            companyId: this.companyId,
            siteId: 1,
            siteName: ""
        };
    this.dialog.open(SiteFloorDetailsComponent, this.config);

    google.maps.event.addListener(shape, 'click', (event) => {

    });

SiteFloorDetailsComponent TypeScript code:

import { Inject, Component, ViewEncapsulation, OnInit, EventEmitter } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';

import { MdDialogRef, MD_DIALOG_DATA } from '@angular/material';

import { AssetsService } from '../../../Services/Assets/assets.service';
import { SlimLoadingBarService } from 'ng2-slim-loading-bar';
import { LowryToastyService } from '../../../Services/Shared/lowrytoasty.service';
import { ErrorLoggerService } from '../../../Services/Shared/errorlogger.service';

@Component({
selector: "SiteFloorDetailsComponent",
templateUrl: '../app/Components/Assets/AssetSearch/site-floor-details.component.html',
providers: [AssetsService]
})
export class SiteFloorDetailsComponent {
siteFloorDetails: any[];
siteName: string;
companyId: number;

constructor(
    @Inject(MD_DIALOG_DATA) private modelPopupData:
        {
            companyId: number, siteId: number, siteName: string
        },
    public dialogRef: MdDialogRef<SiteFloorDetailsComponent>,
    private assetService: AssetsService,
    private slimLoadingBarService: SlimLoadingBarService,
    private lowryToastyService: LowryToastyService,
    private errorLoggerService: ErrorLoggerService,
    private router: Router) {
    this.siteName = this.modelPopupData.siteName;
    this.companyId = this.modelPopupData.companyId;
};

ngOnInit() {
    debugger;

    this.assetService.getBuildingFloorDetails(this.modelPopupData.companyId, this.modelPopupData.siteId).subscribe(
        (jsonData) => {
            this.siteFloorDetails = jsonData;
        },
        (error) => {
            this.errorLoggerService.logErrorToServer("SiteFloorDetailsComponent", "ngOnInit", error);
        },
        () => {
            //this.slimLoadingBarService.complete();
        }
    );
}

closeModel() {
    this.dialogRef.close();
};
}

site-floor-details.component.html:

<h1 md-dialog-title class="primary-color borderBtm ">
Site-Floor Details

</h1>

<md-dialog-content class="accent-color">
<div style="min-width:200px">
    <div class="row" style="text-align:center;">
        <h5>{{siteName}}</h5>
    </div>
    <div class="row">
        <div *ngFor="let item of siteFloorDetails" class="col-md-3">
            <a href="#" [routerLink]="['/RTLSAssets/'+companyId+ '/' + item.FloorId]">{{item.BuildingName}} - {{item.FloorName}}</a>
        </div>
    </div>
</div>
</md-dialog-content>
<md-dialog-actions class="float-right">
    <div style="width:10px;"></div>
    <button type="button" (click)="closeModel()" class="cust-btn">Close</button>
</md-dialog-actions>

If anyone has insights or suggestions on what might be missing, I'd greatly appreciate your assistance.

Answer ā„–1

I have found the solution to the issue. Since events fired from google.map.event occur outside of the Angular context, it is necessary to utilize the NgZone::run method.

   constructor(
     private zone: NgZone) {
   }
   // ...
   google.maps.event.addListener(shape, 'click', (event) => {
        let customData = shape.CustomData;

        this.config.data =
            {
                companyId: this.companyId,
                siteId: customData.SiteId,
                siteName: customData.SiteName
            };
        this.zone.run(() => {
          this.dialog.open(SiteFloorDetailsComponent, this.config);
        });


    });

Answer ā„–2

Ensure that your component includes the OnInit interface, like so:

import {OnInit} from '@angular/core';
// ...
export class SiteFloorDetailsComponent implements OnInit { }

Answer ā„–3

Wow! I just noticed the absence of implements OnInit and immediately found the solution =)

Feel free to correct me if I'm mistaken, but converting the callback into an Observable should also do the trick, and it offers more versatility in the future. You can chain additional operations or side-effects with it. Here's an example:

const mapClickFactory = Observable.fromCallback(google.maps.event.addListener);
const source = mapClickFactory(shape, 'click');

this.subscriptions.push(
    source.subscribe(event => {
        let customData = shape.CustomData;
        this.config.data = {
            companyId: this.companyId,
            siteId: customData.SiteId,
            siteName: customData.SiteName
        };
        this.dialog.open(SiteFloorDetailsComponent, this.config);
    })
);
/* Don't forget to include this.subscriptions.forEach(sub => sub.unsubscribe())
   in the ngOnDestroy() method of this component! */

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

How can I align the isometric camera in THREE.js to the center of a cube?

Hey there, I'm working on a tricky exercise involving setting up a camera and cube with THREE.js. The goal is to maintain the cube's initial ratio while ensuring the camera is focused on the center of the cube. Although I believe I've succes ...

strange complications with importing TypeScript

In my Typescript projects, I frequently use an npm module called common-types (repository: https://github.com/lifegadget/common-types). Recently, I added an enum for managing Firebase projects named FirebaseEvent. Here is how it is defined: export enum Fi ...

What is preventing me from returning the result of $.ajax, but I can return the result of $http.post?

I am facing an issue with having 2 return statements in my code: return $http.post({ url: CHEAPWATCHER.config.domain + 'api/Authenticate', contentType: 'application/x-www-form-urlencoded; charset=UTF-8', data: data }); re ...

What is the best way to bypass using an if/else statement in TypeScript when dealing with mocha and returning undefined values

A unique spline able to be intertwined and produce a new version of itself, most of the time. export default class UniqueSpline { public intertwinedCount: number; constructor(parent?: UniqueSpline) { this.intertwinedCount = parent && pare ...

Activate event in jQuery when clicking on a blank area, away from any div element

I need help figuring out how to hide a div when empty space on the margins of the page is clicked, as opposed to just any area outside of the div. I've managed to achieve this functionality when certain other divs are clicked, but I'm stuck on im ...

Retrieve or update the selected option value in a Select2 multiple dropdown

I'm currently using Select2 for multiselect on an input field. My goal is to identify which choice has been clicked, but when I inspect the event triggered upon clicking a choice ("choice-selected"), all I see is event.target.value which contains the ...

Experimenting with a sample post on a minimalist Node.js application using Mocha and Superagent

I trust you are having a splendid day. Currently, I am focusing on enhancing my TDD skills in Node.js. To practice, I have developed a minimalistic application that handles basic GET and POST requests. The app simply displays a straightforward form to the ...

JavaScript form validation eliminates input data

I recently started using the JavaScript library for client-side form validation called Bouncer. It has been working really well, but I have encountered a peculiar behavior that I need help understanding. My form has two submit buttons with different value ...

Performing a MongoDB upsert operation within an array structure

I am having trouble manipulating the values in an array within my mongoDB. The version I am using is 3.4.23. Below is an example of my collection: { "link": "abc.com", "Values": [{ "valueID": "v1", "date": "05-07-2015", "value": "10 ...

Instructions for setting up qtip2 tooltip with npm in an Angular 2 project

Struggling to integrate qtip2 into my Angular 2 app, encountering errors like this After extensive Google searches, I could not find a definitive solution for installing the qtip2 JQuery plugin via npm to enable tooltips. Even after updating JQuery to ve ...

Exploring shader file content within three.js with the help of jQuery

I am trying to retrieve the content of a string that I have imported using HTML from within another script. To include the text file in question in the html file: <script src="shaders/fragmentshader.fs" id=fragmentshader></script> After impo ...

Tips for retrieving the return value from a function with an error handling callback

I am having an issue with my function that is supposed to return data or throw an error from a JSON web token custom function. The problem I am facing is that the data returned from the signer part of the function is not being assigned to the token const a ...

Managing the ERR_NAME_NOT_RESOLVED issue

Currently, I am facing a task related to the health check endpoint where I need to receive a response from the backend or encounter a net::ERR_NAME_NOT_RESOLVED error if we are outside of a specific network. When attempting to send a request to my endpoin ...

Validating data for Telegram Web Bots using JavaScript

Struggling with creating a user verification script for my Telegram web app bots. Need help troubleshooting. import sha256 from 'js-sha256' const telegram = window.Telegram.WebApp const bot_token = '<bot-token>' const data_check_ ...

Effectively generating observables that extract a designated element from a collection of observables

Within my application, I am utilizing a RxJS subject to broadcast changes within a collection. Each time the collection is updated, the subject emits the new contents as an array format. let collectionSubject = new Rx.BehaviourSubject(); collectionSubjec ...

How can I make a method in VueJS wait to execute until after rendering?

There is a button that triggers the parse method. parse: function() { this.json.data = getDataFromAPI(); applyColor(); }, applyColor: function() { for (var i=0; i<this.json.data.length; i++) { var doc = document.getElementById(t ...

Obtain a collection of the corresponding keys for a given value from dictionaries

I'm implementing a function that retrieves a list of keys associated with a specific value in the dictionary. Although I am able to print out the first key successfully, I'm facing difficulties in displaying subsequent keys. I understand that I ...

What is the best way to display the angular bootstrap modal only upon the initial page load?

Even though I am only intending to show the bootstrap modal on page load, it is triggering every time the route changes. For example, if I return to the same page from another page using the browser's back or forward buttons, the modal is shown again. ...

Is it possible to synchronize functions in node.js with postgresql?

Iā€™m facing some challenges in managing asynchronous functions. Here is the code snippet that's causing the issue: var query = client.query("select * from usuario"); query.on('row', function(user) { var queryInterest = client. ...

Disposing of memory in THREE JS when switching between routes in VUE

Currently, I am delving into the world of VUE JS and working on a basic SPA that navigates through different pages. In my spare time, I have developed several THREE JS demos which unfortunately tend to slow down and eventually halt when switching between ...