I am trying to draw a map when a button is clicked. However, it doesn't seem to work when I use NavController.push(), but only with NavController.setRoot(). I don't get any errors, so I can't figure out what causes this.
This is the class that draws the map:
declare var google: any;
#Component({
selector: 'page-Map',
templateUrl: 'Map.html'
})
export class MapPage {
public directionsService: any;
public directionsDisplay: any;
public directions: any;
map: any;
markers = [];
constructor(private _theme: ThemeService, private shareService: ShareService, public ajaxService: AjaxService) {
let rendererOptions = { draggable: true };
this.directionsService = new google.maps.DirectionsService;
let googleDiplay = new google.maps.DirectionsRenderer(rendererOptions);
this.directionsDisplay = new google.maps.DirectionsRenderer({ draggable: true });
this.initMap();
}
//initialises the map
initMap() {
var point = { lat: 12.65, lng: 12.5683 };
let divMap = (<HTMLInputElement>document.getElementById('map'));
this.map = new google.maps.Map(divMap, {
center: point,
zoom: 15,
disableDefaultUI: true,
draggable: true,
zoomControl: true,
});
let locationOptions = { timeout: 30000, enableHighAccuracy: true, maximumAge: 0 };
navigator.geolocation.getCurrentPosition((position) => {
this.map.setCenter(new google.maps.LatLng(position.coords.latitude, position.coords.longitude));
}, (error) => { }, locationOptions);
//create marker and set to initialised map
var myLatLng = this.map.getCenter();
this.directionsDisplay.setMap(this.map);
}
}
This is the HTML:
<ion-header>
<ion-navbar>
<ion-title>Location</ion-title>
</ion-navbar>
</div>
</ion-header>
<ion-content>
<div id="map"></div>
</ion-content>
Try initializing the map after a platform.ready()
import { Platform } from 'ionic-angular';
constructor(public platform: Platform){
// ...ALL YOUR CODE...
platform.ready().then(() => {
this.initMap();
});
}
And be sure your map has the size it needs via css
#map {
width: 100%;
height: 100%; // 'auto' might work too
}
I have fixed the problem. The reason why it didn't work was that the id='map' was already in use, so I changed the id to id=map3 in the Map.html. So now my HTML file looks like this:
enter code here
I also changed
let divMap = (<HTMLInputElement>document.getElementById('map'));
to
let divMap = (<HTMLInputElement>document.getElementById('map3'));
and the CSS:
#map3 {
height: 100%;
}
and the HTML:
<ion-header>
<ion-navbar>
<ion-title>Location</ion-title>
</ion-navbar>
</div>
</ion-header>
<ion-content>
<div id="map3"></div>
</ion-content>
Related
I have a Ionic App using google maps . I am trying to get latitude and longitude from data json api for flight route then inject that data arrays to Google Maps polyline . Fetch data json api working fine without problem , but when l put objects inside Google Maps l get error
ERROR Error: Uncaught (in promise): TypeError: Cannot use 'in' operator to search for 'getPosition' in 40.11882
TypeError: Cannot use 'in' operator to search for 'getPosition' in 40.11882
at getLatLng (Common.js:544)
at Array.map (<anonymous>)
at Object.convertToPositionArray (Common.js:575)
at Map.addPolyline (Map.js:1231)
at vendor.js:76340
my code
export class HomePage{
map: GoogleMap;
latitude: any;
longitude: any;
dates=[]
constructor(
public toastCtrl: ToastController,
private platform: Platform,
private http: HTTP
) { }
ngOnInit() {
// Since ngOnInit() is executed before `deviceready` event,
// you have to wait the event.
this.platform.ready();
this.getmarker();
this.loadMap();
}
async getmarker(){
this.http.get('/v1/flightjson?flightId=201',{},{})
.then( data=>{
// this.latitude = JSON.parse(data.data).result.response.data.flight.track.latitude
// this.longitude = JSON.parse(data.data).result.response.data.flight.track
for(let datas of JSON.parse(data.data).result.response.data.flight['track']) {
this.longitude = datas.longitude
this.latitude = datas.latitude
console.log(this.longitude, this.latitude)
}
})
}
loadMap() {
let AIR_PORTS = [
this.longitude = datas.longitude
this.latitude = datas.latitude
];
console.log(AIR_PORTS)
this.map = GoogleMaps.create('map_canvas');
let polyline: Polyline = this.map.addPolylineSync({
points: AIR_PORTS,
color: '#AA00FF',
width: 10,
geodesic: true,
clickable: true // clickable = false in default
});
polyline.on(GoogleMapsEvent.POLYLINE_CLICK).subscribe((params: any) => {
let position: LatLng = <LatLng>params[0];
let marker: Marker = this.map.addMarkerSync({
position: position,
title: position.toUrlValue(),
disableAutoPan: true
});
marker.showInfoWindow();
});
}
}
console log for AIR_PORTS
my data json url
original code
export class PolylinePage implements OnInit {
map: GoogleMap;
constructor(private platform: Platform) { }
async ngOnInit() {
// Since ngOnInit() is executed before `deviceready` event,
// you have to wait the event.
await this.platform.ready();
await this.loadMap();
}
loadMap() {
let HND_AIR_PORT = {lat: 35.548852, lng: 139.784086};
let SFO_AIR_PORT = {lat: 37.615223, lng: -122.389979};
let HNL_AIR_PORT = {lat: 21.324513, lng: -157.925074};
let AIR_PORTS = [
HND_AIR_PORT,
HNL_AIR_PORT,
SFO_AIR_PORT
];
this.map = GoogleMaps.create('map_canvas', {
camera: {
target: AIR_PORTS
}
});
let polyline: Polyline = this.map.addPolylineSync({
points: AIR_PORTS,
color: '#AA00FF',
width: 10,
geodesic: true,
clickable: true // clickable = false in default
});
polyline.on(GoogleMapsEvent.POLYLINE_CLICK).subscribe((params: any) => {
let position: LatLng = <LatLng>params[0];
let marker: Marker = this.map.addMarkerSync({
position: position,
title: position.toUrlValue(),
disableAutoPan: true
});
marker.showInfoWindow();
});
}
}
i think the way you are reading data and passing data to the GoogleMap is incorrect, Please try the following
export class HomePage{
map: GoogleMap;
points: {lng: number, lat: number}[] = [];
constructor(
public toastCtrl: ToastController,
private platform: Platform,
private http: HTTP
) { }
ngOnInit() {
this.platform.ready();
this.getmarker();
this.loadMap();
}
async getmarker(){
this.http.get('/v1/flightjson?flightId=201',{},{})
.then( data=>{
for(let datas of JSON.parse(data.data).result.response.data.flight['track']) {
this.points.push({lng: datas.longitude, lat: datas.latitude});
}
})
}
loadMap() {
let AIR_PORTS = this.points;
console.log(AIR_PORTS)
this.map = GoogleMaps.create('map_canvas');
let polyline: Polyline = this.map.addPolylineSync({
points: AIR_PORTS,
color: '#AA00FF',
width: 10,
geodesic: true,
clickable: true // clickable = false in default
});
polyline.on(GoogleMapsEvent.POLYLINE_CLICK).subscribe((params: any) => {
let position: LatLng = <LatLng>params[0];
let marker: Marker = this.map.addMarkerSync({
position: position,
title: position.toUrlValue(),
disableAutoPan: true
});
marker.showInfoWindow();
});
}
}
you can find a working example here which i tried with your data - Example Demo.
And code from here Example Code
I'm building a project in Ionic 3, I'm using the native maps plugin for Ionic, I can show the map and I can add a marker in a selected address, but I have not managed to show the recommended route on the map.
HTML:
<div id="map"></div>
TS:
loadMap(){
var lat = this.placeInfo.latitudeFrom;
var lng = this.placeInfo.longitudeFrom;
let mapOptions: GoogleMapOptions = {
camera: {
target: {
lat: lat,
lng: lng,
gestureHandling: 'none',
zoomControl: true
},
zoom: 18,
tilt: 30,
}
};
this.map = GoogleMaps.create('map', mapOptions);
this.map.one(GoogleMapsEvent.MAP_READY)
.then(() => {
let marker: Marker = this.map.addMarkerSync({
title: 'Ionic',
icon: 'blue',
animation: 'DROP',
position: {
lat: lat,
lng:lng
}
});
})
.catch(error =>{
console.log('error: ', error);
});
}
I'm trying this, but does not work
displayRoutev2() {
this.directionsService.route({
origin: this.placeInfo.startPoint,
destination: this.placeInfo.endPoint,
travelMode: 'DRIVING'
}, (response, status) => {
if (status === 'OK') {
this.directionsDisplay.setDirections(response);
this.directionsDisplay.setMap(this.map);
} else {
window.alert('No se encontraron rutas disponibles.' + status);
}
});
var service = new google.maps.DistanceMatrixService();
}
Can I use the var "service" to call any function? Or I need to try another way?
I can show route with another way that is not the better way, I need to use this native way, someone knows whats I can do?
import {AfterViewInit, Component, ElementRef, OnInit, ViewChild} from '#angular/core';
import {FormBuilder, FormGroup, Validators} from '#angular/forms';
declare var google;
#Component({
selector: 'app-direction',
templateUrl: './direction.page.html',
styleUrls: ['./direction.page.scss'],
})
export class DirectionPage implements OnInit, AfterViewInit {
#ViewChild('mapElement') mapNativeElement: ElementRef;
#ViewChild('directionsPanel') directionsPanel: ElementRef;
directionsService = new google.maps.DirectionsService;
directionsDisplay = new google.maps.DirectionsRenderer;
directionForm: FormGroup;
constructor(private fb: FormBuilder) {
this.createDirectionForm();
}
ngOnInit() {
}
createDirectionForm() {
this.directionForm = this.fb.group({
source: ['', Validators.required],
destination: ['', Validators.required]
});
}
ngAfterViewInit(): void {
const map = new google.maps.Map(this.mapNativeElement.nativeElement, {
zoom: 7,
center: {lat: 41.85, lng: -87.65}
});
this.directionsDisplay.setMap(map);
directionsDisplay.setPanel(this.directionsPanel.nativeElement);
}
DisplayRoute(formValues) {
const that = this;
this.directionsService.route({
origin: formValues.source,
destination: formValues.destination,
travelMode: 'DRIVING'
}, (response, status) => {
if (status === 'OK') {
that.directionsDisplay.setDirections(response);
} else {
window.alert('Directions request failed due to ' + status);
}
});
}
}
==In home.page.ts==
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-menu-button></ion-menu-button>
</ion-buttons>
<ion-title>Direction</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<form [formGroup]="directionForm" (ngSubmit)="DisplayRoute(directionForm.value)">
<ion-item>
<ion-label position="floating">Source</ion-label>
<ion-input formControlName="source"></ion-input>
</ion-item>
<ion-item>
<ion-label position="floating">Destination</ion-label>
<ion-input formControlName="destination"></ion-input>
</ion-item>
<ion-button expand="full" type="submit" [disabled]="directionForm.invalid">Get Direction</ion-button>
</form>
<ion-card>
<ion-card-content>
<div #directionsPanel></div>
</ion-card-content>
</ion-card>
<div #mapElement class="map"></div>
</ion-content>
I'm using ionic 2 and trying to load google map using its JS API.
Here is my code:
import { Component, ViewChild, ElementRef } from '#angular/core';
import { NavController, Platform, NavParams } from 'ionic-angular';
declare var google;
#Component({
selector: 'page-map',
templateUrl: 'map.html',
})
export class MapPage {
#ViewChild('map') mapElement: ElementRef;
map: any;
latitude : any;
longitude : any;
constructor(public platform: Platform, public navCtrl: NavController,public navParams: NavParams) {
this.platform = platform;
this.initializeMap();
}
ionViewDidLoad(){
this.initializeMap();
}
initializeMap() {
this.platform.ready().then(() => {
var minZoomLevel = 12;
this.map = new google.maps.Map(document.getElementById('map'), {
zoom: minZoomLevel,
center: new google.maps.LatLng(38.50, -90.50),
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var position = new google.maps.LatLng("23.032612699999998", "72.56187790000001");
var dogwalkMarker = new google.maps.Marker({position: position, title: "Testing"});
dogwalkMarker.setMap(this.map);
});
}
}
I have also added reference of the JS in my index.html file before cordova.js:
<script src="http://maps.google.com/maps/api/js"></script>
Here is my html:
<ion-header>
<ion-navbar hideBackButton side="left">
<ion-title style="margin-left: 0px;"><span class="menuTitle">Map</span></ion-title>
</ion-navbar>
</ion-header>
<ion-content>
<div #map id="map"></div>
</ion-content>
The code does not display any error but when I try to load this page it displays error like:
Uncaught (in promise): TypeError: Cannot read property 'firstChild' of null
Use mapElement
Typescript file
let minZoomLevel = 12;
let mapOptions = {
zoom: minZoomLevel,
center: new google.maps.LatLng(38.50, -90.50),
mapTypeId: google.maps.MapTypeId.ROADMAP
}
this.map = new google.maps.Map(this.mapElement.nativeElement, mapOptions);
I have implemented Google maps in Angular2 without using any of the npm libraries available and need to add a button to the infoWindow that fires an Angular function. Can this be done???.
My best effort so far does not work, the airport.name shows but the (click)="setAirport('departure', airport)" does not. I assume it's not connected to Angular in any way.
My component has the following function when the user clicks to activate the marker & infoWindow.
showAirport(idx, airport) {
const markerInfo =
<h4>${airport.name}</h4><div class='row' style='margin:0; margin-top:20px'>
<div class="col-xs-6">
<a class="btn btn-primary btn-block" (click)="setAirport('departure',airport)">Set as Departure</a>
</div>
<div class="col-xs-6">
<a class="btn btn-primary btn-block" (click)="setAirport('arrival',airport)">Set as Arrival</a>
</div>
</div>
;
this.setCurrentAirport(idx);
this.infoWindow.setContent(markerInfo);
this.infoWindow.open(this.map, this.markers[idx]);
}
Here is more of the component ts file.
import { Component, ViewChild, ElementRef, OnInit } from '#angular/core';
import { Response } from '#angular/http';
declare var google;
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
#ViewChild('map') mapElement: ElementRef;
map: any;
infoWindow = new google.maps.InfoWindow();
private allItems: any[];
lat = 51.5287718;
lng = -0.1;
airports = [];
markers = [];
flights = [];
polylines = [];
bounds = {
w: 0,
e: 0,
n: 0,
s: 0
};
loadAirports(apiBounds) {
this.airportsService.byBounds(apiBounds)
.subscribe(
(airportData: any[]) => {
for (let i = 0; i < airportData['data'].length; i++) {
const tmpAirport = {
id: i,
airportID: airportData['data'][i].id,
name: airportData['data'][i].airportName,
lat: airportData['data'][i].lat,
lng: airportData['data'][i].lng
};
this.airports.push(tmpAirport);
this.addMarker(tmpAirport, tmpAirport['name'], i);
}
},
(error: Response) => {
const errorData = error.json();
}
);
};
showAirport(idx, airport) {
console.log(airport);
// this is where I want to be able to include the buttons
const markerInfo = `<h4>${airport.name}</h4>`;
this.infoWindow.setContent(markerInfo);
this.infoWindow.open(this.map, this.markers[idx]);
}
loadMap() {
const latLng = new google.maps.LatLng(51, -0.5);
const mapOptions = {
center: latLng,
scrollwheel: false,
zoom: 9,
minZoom: 6,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
this.map = new google.maps.Map(this.mapElement.nativeElement, mapOptions);
new google.maps.event.addListenerOnce(this.map, 'bounds_changed', () => {
this.loadAirports(this.bounds);
});
}
addMarker(airport, info, markerIndex) {
const position = new google.maps.LatLng(airport['lat'], airport['lng']);
const marker = new google.maps.Marker({
map: this.map,
position: position,
markerIndex: markerIndex
});
const markerInfo = '<b>' + airport.name + '</b>';
this.addInfoWindow(marker, markerInfo, markerIndex);
this.markers.push(marker);
}
addInfoWindow(marker, content, markerIndex) {
google.maps.event.addListener(marker, 'click', () => {
this.infoWindow.setContent(content);
this.infoWindow.open(this.map, marker);
});
}
constructor() {}
ngOnInit() {
this.loadMap();
}
}
Not the prettiest solution, but you could always assign clases/ids to the buttons inside the InfoWindow, and then bind to them:
showAirport(idx, airport) {
console.log(airport);
// this is where I want to be able to include the buttons
const markerInfo = `
<h4>${airport.name}</h4>
<a class="btn btn-primary btn-block" id="departure-button">Set as Departure</a>
`;
this.infoWindow.setContent(markerInfo);
this.infoWindow.open(this.map, this.markers[idx]);
const departureButton = this.mapElement.nativeElement.getElementById('departure-button');
departureButton.onclick = this.setAirport('departure', airport);
google.maps.event.addListener(this.infoWindow, 'closeclick', () => {
departureButton.onclick = null;
});
});
Just assign this to that and use it,
addInfoWindow(marker, content, markerIndex) {
let that = this;
google.maps.event.addListener(marker, 'click', () => {
that.infoWindow.setContent(content);
that.infoWindow.open(this.map, marker);
});
}
Crazy right ;). variable scope for this is not the this that you need so this don't have infoWindow but by assigning this to that now we have infowWindow.
I guess it should be simple for the ionic/Angular people.
from some reason, I can't get this simple script to work (Ionic2 with GMaps).
Here is my code:
Map.html:
<ion-navbar *navbar>
<button menuToggle>
<ion-icon name="menu"></ion-icon>
</button>
<ion-title>Google Map</ion-title>
<ion-buttons end>
<button (click)="addMarker()">
<ion-icon name="add"></ion-icon>Add Marker
</button>
</ion-buttons>
</ion-navbar>
<ion-content padding class="map">
<div id="map"></div>
</ion-content>
Map.ts:
import {Page, NavController, Platform} from 'ionic-angular';
import {Geolocation} from 'ionic-native';
/*
Generated class for the MapPage page.
See http://ionicframework.com/docs/v2/components/#navigation for more info on
Ionic pages and navigation.
*/
#Page({
templateUrl: 'build/pages/map/map.html',
})
export class MapPage {
constructor(public nav: NavController, platform: Platform) {
this.nav = nav;
this.map = null;
// this.platform = platform;
// this.initializeMap();
this.platform = platform;
platform.ready().then(() => {
this.loadMap();
});
}
loadMap(){
let options = {timeout: 10000, enableHighAccuracy: true};
Geolocation.getCurrentPosition(options).then((position) => {
let latLng = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
let mapOptions = {
center: latLng,
zoom: 15,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
this.map = new google.maps.Map(document.getElementById("map"), mapOptions);
});
}
}
I have added my code here (Ionic2 project with Gmap inside):
http://plnkr.co/edit/ERnCxooM1IWD3qVLMQ1K?p=preview
you can find inside: "home.ts" the script, I have comment the code below, since in the moment I'm adding it back All of my ionic project is down, you can try and uncomment it.
I also have found Angular2 with Gmap project, But I couldn't find Ionic2 project with Gmap. here:
Angular2 Gmap
Anyone can see what is wrong there?
Thank you very much!
Eran.
Check if you installed the plugin a correct way.
Validate your API keys at console.developers.google.com
Be sure the HTML element where the maps get injected into has a
predefined height property.
Be sure you run your app on a connected or virtual
device.
If that doesn't work: I've created an Ionic 2.0.0-rc.5 starter with minimal functionality https://github.com/0x1ad2/ionic2-starter-google-maps
I have created an example app with ionic2 and google map.
https://github.com/nazrul104/google-map-with-ionic2. It may help you!
Thanks to #Nazrul here is the changes I made in my ts page file:
export class Page1 {
constructor() {
this.loadMap();
}
loadMap(){
let options = {timeout: 10000, enableHighAccuracy: true};
//ENABLE THE FOLLOWING:
Geolocation.getCurrentPosition(options).then((position) => {
let latLng = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
let mapOptions = {
center: latLng,
zoom: 15,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
this.map = new google.maps.Map(document.querySelector('#map'), mapOptions);
var x = document.querySelector('#map');
console.log(x);
});
}
}
Now I can see the map :)
My solution was, do not initialize the map on the constructor, initialize it on the ionViewDidLoad.
ionViewDidLoad() {
console.log('ionViewDidLoad Maps');
setTimeout(()=>{
this.loadMap();
}, 1000)
}