I am trying to integrate google map in ionic 4 application, and unfortunately facing nativeElement not found error.
@ViewChild('Map') mapElement: ElementRef; ~~~~~~~~~~~~~~~~
node_modules/@angular/core/core.d.ts:8436:47 8436 (selector: Type | Function | string, opts: { ~~~~~~~ 8437 read?: any; ~~~~~~~~~~~~~~~~~~~ 8438 static: boolean; ~~~~~~~~~~~~~~~~~~~~~~~~ 8439 }): any; ~~~~~ An argument for 'opts' was not provided. System console .
home.page.ts
import {Component, ElementRef, NgZone, ViewChild, OnInit} from '@angular/core';
import {Geolocation} from '@ionic-native/geolocation/ngx';
declare var google: any;
@Component({
selector: 'app-home',
templateUrl: 'home.page.html',
styleUrls: ['home.page.scss'],
})
export class HomePage {
@ViewChild('Map') mapElement: ElementRef;
map: any;
mapOptions: any;
location = {lat: null, lng: null};
markerOptions: any = {position: null, map: null, title: null};
marker: any;
apiKey: any = 'API_KEY';
constructor(public zone: NgZone, public geolocation: Geolocation) {
/*load google map script dynamically */
const script = document.createElement('script');
script.id = 'googleMap';
if (this.apiKey) {
script.src = 'https://maps.googleapis.com/maps/api/js?key=' + this.apiKey;
} else {
script.src = 'https://maps.googleapis.com/maps/api/js?key=';
}
document.head.appendChild(script);
/*Get Current location*/
this.geolocation.getCurrentPosition().then((position) => {
this.location.lat = position.coords.latitude;
this.location.lng = position.coords.longitude;
});
/*Map options*/
this.mapOptions = {
center: this.location,
zoom: 21,
mapTypeControl: false
};
setTimeout(() => {
this.map = new google.maps.Map(this.mapElement.nativeElement, this.mapOptions);
/*Marker Options*/
this.markerOptions.position = this.location;
this.markerOptions.map = this.map;
this.markerOptions.title = 'My Location';
this.marker = new google.maps.Marker(this.markerOptions);
}, 3000);
}
}
Newer versions of Angular require you to provide an object as a second parameter to the @ViewChild
decorator (docs). That object needs to have a boolean value for static
.
// {static: boolean}
@ViewChild('Map', {static: false) mapElement: ElementRef;
Deciding ifstatic
should be true or false comes down to whether or not you are dynamically rendering the element in your template, like with *ngIf
or *ngFor
. If you're not using those (or any other structural directives), you should set static
to false so that you can access the element as soon as possible.
Speaking of when you can access the element reference, you have a lot of logic in your component constructor. It is highly recommended that you move it out of the constructor and into a lifecycle hook. You will absolutely need to move any code referencing mapElement
out of the constructor as it will always be undefined there (this might be why you are using a setTimeout
?). ElementRef
s with {static:false}
will be available in ngOnInit
, whereas ElementRef
s with {static:true}
will be available in ngAfterViewInit
.
Since you are using Ionic, it would also be good for you to have a look at their lifecycle hooks as well.