I am showing maps in Ionic 5 with the javascript sdk. I load these maps with a service created for that.
Everything is fine when I do it in pages but if I show one of those pages as modal, the map does not load and the marker places it on the page from which the modal window was opened instead of in the modal window itself.
Let's see if I can put the code below so that it is not too "heavy"
home.page.html
<ion-header [translucent]="true">
<ion-toolbar>
<ion-title>
HOME
</ion-title>
</ion-toolbar>
</ion-header>
<ion-content [fullscreen]="true">
<div id="map"></div>
<ion-button href = "page2" expand = "block">page 2</ion-button>
<ion-button (click)="presentModal()" expand = "block" >page 3 modal</ion-button>
</ion-content>
page2.page.html
<ion-header>
<ion-toolbar>
<ion-title>page2</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<div id="map"></div>
<ion-button href = "home" expand = "block" >home</ion-button>
</ion-content>
page3.page.html
<ion-header>
<ion-toolbar>
<ion-title>page3</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<div id="map"></div>
<ion-button href = "home" expand = "block" >home</ion-button>
</ion-content>
home.page.ts
import { Component, OnInit } from '@angular/core';
import { ModalController } from '@ionic/angular';
import { LocationService } from 'src/app/services/Location.service'
import { Page3Page } from 'src/app/pages/page3/page3.page';
@Component({
selector: 'app-home',
templateUrl: 'home.page.html',
styleUrls: ['home.page.scss'],
})
export class HomePage {
constructor(public LocationService: LocationService,
public ModalController: ModalController) {}
ngOnInit () {
this.LocationService.loadMap("home");
}
async presentModal() {
const modal = await this.ModalController.create({
component: Page3Page
});
return await modal.present();
}
}
page2.page.ts
import { Component, OnInit } from '@angular/core';
import { LocationService } from 'src/app/services/Location.service'
@Component({
selector: 'app-page2',
templateUrl: './page2.page.html',
styleUrls: ['./page2.page.scss'],
})
export class Page2Page implements OnInit {
constructor(private LocationService: LocationService) {}
ngOnInit () {
//this.loadMap();
this.LocationService.loadMap("page2");
}
}
page3.page.ts
import { Component, OnInit } from '@angular/core';
import { LocationService } from 'src/app/services/Location.service'
@Component({
selector: 'app-page3',
templateUrl: './page3.page.html',
styleUrls: ['./page3.page.scss'],
})
export class Page3Page implements OnInit {
constructor(private LocationService: LocationService) {}
ngOnInit() {
this.LocationService.loadMap("page3");
}
}
location.service.ts
import { Injectable } from '@angular/core';
declare var google;
interface Marker {
position: {
lat: number,
lng: number,
};
title: string;
}
@Injectable({
providedIn: 'root'
})
export class LocationService {
map = null;
constructor() { }
loadMap(prmtrMapId) {
// create a new map by passing HTMLElement
const mapEle: HTMLElement = document.getElementById('map');
var myLatLng, myTitle;
var marker;
// create LatLng object
switch (prmtrMapId) {
case "home": // No hay sentencia "break" en el 'case 0:', por lo tanto este caso también será ejecutado
myLatLng = {lat: 54.1675272, lng: -7.5138625}; //england
myTitle = "home -> England";
break; // Al encontrar un "break", no será ejecutado el 'case 2:'
case "page2":
myLatLng = {lat: 51.713614, lng: 10.956151}; //deutschland
myTitle = "page2 -> Deutschland ";
break;
case "page3":
myLatLng = {lat: 47.820012, lng: 3.490945}; //france
myTitle = "page3 modal -> France";
break;
default:
myLatLng = {lat: 4.658383846282959, lng: -74.09394073486328};
}
marker = {
position: myLatLng,
title: myTitle
};
// create map
this.map = new google.maps.Map(mapEle, {
center: marker.position,
zoom: 4
});
google.maps.event.addListenerOnce(this.map, 'idle', () => {
this.addMarker(marker);
});
}
addMarker(marker: Marker) {
return new google.maps.Marker({
position: marker.position,
map: this.map,
title: marker.title
});
}
}
Any help is apreciated !
thanks a lot
Ernesto
You can use the elementRef and pass it along like this:
Change the service to this:
loadMap(prmtrMapId, elRef: ElementRef) {
const mapEle: HTMLElement = elRef.nativeElement;
}
In Page3 change the html to
<ion-content>
<div #map></div>
<ion-button href = "home" expand = "block" >home</ion-button>
</ion-content>
and in the ts add the ViewChild and call the service like this
@ViewChild('map') mapEl: ElementRef;
ngAfterViewInit(){
this.LocationService.loadMap("page3", this.mapEl);
}
Because "View queries are set before the ngAfterViewInit callback is called." You need to use ngAfterViewInit or static: true.