Search code examples
javascriptangularhere-api

Here Map Angular Component Not loading in Modal Component


Using Here Map to show stops for a shipment, where using the shipment id to fetch the details of those stops. Loading the here map from the Modal Component.

jsmap-show-modal.component.html

<app-modal [title]="header">
  <ng-template appModalBody>
    <div><jsapp-map [shipmentId]="shipmentId"></jsapp-map></div>
  </ng-template>
</app-modal>

jsmap-show-modal.component.ts

import { Component, Inject, Input, OnInit } from '@angular/core';
import { MAT_DIALOG_DATA } from '@angular/material';

@Component({
  selector: 'app-jsmap-show-modal',
  templateUrl: './jsmap-show-modal.component.html',
  styleUrls: ['./jsmap-show-modal.component.scss']
})
export class JsMapShowModalComponent implements OnInit {
  public shipmentId: string;
  public header: string;
  constructor(@Inject(MAT_DIALOG_DATA) public data: any){
    console.log(data);
    this.header = data.header;
    this.shipmentId = data.shipmentId ;
  }
  ngOnInit() {}
}

Declared the jsModalComponent at necessary modules at the entryComponents property in the @NgModule directive.

Here is the code in jsmap.component.ts

@Component({
  selector: 'jsapp-map',
  templateUrl: './jsmap.component.html',
  styleUrls: ['./jsmap.component.scss']
})
export class JsmapComponent {
@Input() shipmentId: string;
  private platform: any;
  private map: any;
  private router: any;
  private locations: any;
  private waypoints: any;
  private tripId: string;

  constructor(
    private jsmapService: JsmapService,
    private route: ActivatedRoute) {
    this.platform = new H.service.Platform({
      apikey: <<MY_API_KEY>>
    });
  }

ngOnInit(): void {
    this.initializeMap();
    this.calculateRoute();
  }

initializeMap(): void {
    const defaultLayers = this.platform.createDefaultLayers();
    this.map = new H.Map(document.getElementById('mapContainer'), defaultLayers.vector.normal.map, {
      zoom: 10,
      center: { lat: 40.397694, lng: -105.073181 },
      pixelRatio: window.devicePixelRatio || 1
    });
    const ui = H.ui.UI.createDefault(this.map, defaultLayers);
    const behavior = new H.mapevents.Behavior(new H.mapevents.MapEvents(this.map));
  }

  calculateRoute(): void {
    this.fetchStopDetailsAndGenerateWaypoints();
  }

onRouteSuccess(result: any): void {
    const route = result.response.route[0];

    const lineString = new H.geo.LineString();
    route.shape.forEach((point: any) => {
      const parts = point.split(',');
      lineString.pushLatLngAlt(parts[0], parts[1]);
    });

    const routePolyline = new H.map.Polyline(lineString, {
      style: { strokeColor: 'blue', lineWidth: 3 }
    });

    this.map.addObject(routePolyline);

    route.waypoint.forEach((waypoint: any, index: number) => {
      const marker = new H.map.Marker({
        lat: waypoint.mappedPosition.latitude,
        lng: waypoint.mappedPosition.longitude
      });
      this.map.addObject(marker);
      marker.label = index + 1;
    });

    this.map.getViewModel().setLookAtData({ bounds: route.boundingBox });
  }

async fetchStopDetailsAndGenerateWaypoints(): Promise<void> {
    const request = new StopDetailsRequest(null, this.shipmentId);
    try {
      const response = await this.jsmapService.getStopDetails(request).toPromise();
      if (response.data && response.data.StopDetailDTOList) {
        const stopDetails: StopDetail[] = response.data.StopDetailDTOList.map(item => ({
          stopName: item.StopName,
          stopAlias: item.StopAlias,
          shipmentName: item.ShipmentName,
          stopSequence: item.StopSequence,
          latitude: item.Latitude,
          longitude: item.Longitude,
          estimatedDispatcherArrival: item.EstimatedDispatcherArrival,
          estimatedDispatcherDeparture: item.EstimatedDispatcherDeparture
        }));

        this.locations = this.generateLocationsFromDTO(stopDetails);
        this.waypoints = this.generateWaypoints(this.locations);

        // Use locations and waypoints as needed
        console.log(this.locations);
        console.log(this.waypoints);
        const routingParameters: { [key: string]: any } = {
          mode: 'fastest;car',
          representation: 'display'
        };

        for (const key in this.waypoints) {
          if (this.waypoints.hasOwnProperty(key)) {
            routingParameters[key] = this.waypoints[key];
          }
        }

        this.router = this.platform.getRoutingService();
        this.router.calculateRoute(routingParameters, this.onRouteSuccess.bind(this), this.onRouteError.bind(this));
      } else {
        console.error('Invalid response format: stopDetailDTOList is not an array');
      }
    } catch (error) {
      // Handle the error here
      console.error(error);
    }
  }

jsmap.component.html

<div id="mapContainer" style="width: 100%; height: 500px;"></div>

On debugging, Can see that the code is working and it is fetching the necessary details to populate the lat and long on the map but somehow it is not loading on the modal box.

Output:

enter image description here

Please help and guide!


Solution

  •  ngAfterViewInit(): void {
     window.setTimeout(()=>{
      this.initializeMap();
      this.calculateRoute();
    }, 500);
    

    Adding a delay worked! Since the modal DOM didn't load in time and the response coming in from the Here Map API couldn't find the mapContainer id, due to which it was unable to initialise the map and then other requests to map the lat and long for the stop didn't go to Here map API.