How to display route with native google maps on Ionic 3 - google-maps

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>

Related

Array Length From Google Geolocation (Ionic)

Could someone point me in the direction of the correct syntax to use to return the value of results from Google Place Search. Like if my search returned 5 locations, I would like to pull the value of 5 from my array and display that information in my app "5 places have been found!". I have managed to get a list of places nearby. But I am not sure how to get a value.
Right now I use this code to access the array of Google Places Search Results
goToDirectionPage(index){
console.log(this.places);
console.log("index" + index);
let selectedPlace = this.places[index].geometry.location;
console.log(selectedPlace);
this.navCtrl.push(DirectionPage, {
origin: this.currentLocation,
destination: selectedPlace
});
}
Here is the code to the Google Places Search
import { Component} from '#angular/core';
import { NavController, NavParams } from 'ionic-angular';
/**
* Generated class for the DirectionPage page.
*
* See https://ionicframework.com/docs/components/#navigation for more info on
* Ionic pages and navigation.
*/
declare var google;
#Component({
selector: 'page-direction',
templateUrl: 'direction.html',
})
export class DirectionPage {
origin: any;
destination: any;
map: any;
constructor(public navCtrl: NavController, public navParams: NavParams) {
this.origin = navParams.get('origin');
this.destination = navParams.get('destination');
this.map = navParams.get('map');
}
ionViewDidLoad() {
this.calculateRoute();
console.log('ionViewDidLoad DirectionPage');
}
calculateRoute(){
let mapOptions = {
center: this.origin,
zoom: 10,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
this.map = new google.maps.Map(document.getElementById("directionMap"), mapOptions);
let directionsService = new google.maps.DirectionsService();
let directionsDisplay = new google.maps.DirectionsRenderer();
directionsDisplay.setMap(this.map);
let request = {
origin: this.origin,
destination: this.destination,
travelMode: google.maps.TravelMode.DRIVING
};
directionsService.route(request, function(response, status){
if(status == google.maps.DirectionsStatus.OK){
directionsDisplay.setDirections(response);
directionsDisplay.setPanel(document.getElementById('directionPanel'));
}else{
console.warn(status);
}
});
}
}
Desired Result
In places.html
<ion-card>
<ion-item ng-if = "places" >
Places Found: {{places?.length}}
</ion-item>
</ion-card>
<ion-card id="result"> </ion-card>
<button ion-item *ngFor = "let place of places; let i = index" (click)="goToDirectionPage(i)">
{{place.name}} + <br/> {{place.vicinity}} <br /> Average Rating: {{place.rating}}
</button>
</ion-list>

NavController's push doesn't show Google Maps

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>

Can I add an Angular2 (click) to a Google maps marker infoWindow?

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.

InvalidValueError: setCenter: not a LatLng or LatLngLiteral: in property lng: not a number

I am working on angular2-google-maps, but while implementing I am consistently getting this error
InvalidValueError: setCenter: not a LatLng or LatLngLiteral: in
property lng: not a number
please see my code
import { AgmCoreModule, MapsAPILoader, GoogleMapsAPIWrapper } from 'angular2-google-maps/core';
import { MapDirective } from './map.directive';
declare var google: any;
#Component({
selector: 'map-component',
templateUrl: './map.component.html',
styleUrls: ['./map.component.css',],
providers: [GoogleMapsAPIWrapper]
})
export class MapComponent implements OnInit {
geoloc: marker;
ngOnInit(): void {
navigator.geolocation.getCurrentPosition((position) => {
this.lat = <number>position.coords.latitude;
this.lng = <number>position.coords.longitude;
});
}
// google maps zoom level
zoom: number = 18;
// initial center position for the map
lat: number;
lng: number;
clickedMarker(label: string, index: number) {
console.log(`clicked the marker: ${label || index}`)
}
mapClicked($event: any) {
this.markers.push({
lat: $event.coords.lat,
lng: $event.coords.lng,
draggable: true
});
}
markerDragEnd(m: marker, $event: MouseEvent) {
console.log('dragEnd', m, $event);
}
markers: marker[] = [
{
lat: 51.673858,
lng: 7.815982,
label: 'A',
draggable: true
},
{
lat: 51.373858,
lng: 7.215982,
label: 'B',
draggable: false
},
{
lat: 51.723858,
lng: 7.895982,
label: 'C',
draggable: true
}
]
}
// just an interface for type safety.
interface marker {
lat: number;
lng: number;
label?: string;
draggable: boolean;
}
.sebm-google-map-container {
height: 100%;
}
<sebm-google-map
[latitude]="lat"
[longitude]="lng"
[zoom]="zoom"
[disableDefaultUI]="false"
[zoomControl]="true"
[mapTypeControl]="true"
(mapClick)="mapClicked($event)">
<!--<sebm-google-map-marker
(markerClick)="clickedMarker(geoloc.label, i)"
[latitude]="geoloc.lat"
[longitude]="geoloc.lng"
[label]="geoloc.label"
[markerDraggable]="geoloc.draggable"
(dragEnd)="markerDragEnd(geoloc, $event)">-->
<sebm-google-map-marker
*ngFor="let m of markers; let i = index"
(markerClick)="clickedMarker(m.label, i)"
[latitude]="m.lat"
[longitude]="m.lng"
[label]="m.label"
[markerDraggable]="m.draggable"
(dragEnd)="markerDragEnd(m, $event)">
<sebm-google-map-info-window>
<strong>InfoWindow content</strong>
</sebm-google-map-info-window>
</sebm-google-map-marker>
<sebm-google-map-circle [latitude]="lat + 0.3" [longitude]="lng"
[radius]="5000"
[fillColor]="'red'"
[circleDraggable]="true"
[editable]="true">
</sebm-google-map-circle>
</sebm-google-map>
its giving me my location on map but while using same coordinates its giving error.. please help

Angular 2 HTTP GET with TypeScript google geocode service

I am new to angular2 and trying to find the coordinates(latitude,longitude) using the location.
here is my code,
GeoService.ts
import { Injectable } from '#angular/core';
import { Http } from '#angular/http';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/toPromise';
#Injectable()
export class GeoService {
constructor(private http: Http) { }
getLocation(term: string) {
return this.http.get('http://maps.google.com/maps/api/geocode/json?address=' + term + 'CA&sensor=false').map
((response) => response.json());
}
// tslint:disable-next-line:eofline
}
app.component.html
<!DOCTYPE HTML>
<h1> {{title}} </h1>
<input type="text" [(ngModel)]="location" />
<button (click)="findLocation($event)">Find location</button>
<sebm-google-map
[latitude]="lat"
[longitude]="lng"
[zoom]="zoom"
[disableDefaultUI]="false"
[zoomControl]="false"
(mapClick)="mapClicked($event)">
<sebm-google-map-marker
*ngFor="let m of markers; let i = index"
(markerClick)="clickedMarker(m.label, i)"
[latitude]="m.lat"
[longitude]="m.lng"
[label]="m.label"
[markerDraggable]="m.draggable"
(dragEnd)="markerDragEnd(m, $event)">
<sebm-google-map-info-window>
<strong>InfoWindow content</strong>
</sebm-google-map-info-window>
</sebm-google-map-marker>
<sebm-google-map-circle [latitude]="lat + 0.3" [longitude]="lng"
[radius]="5000"
[fillColor]="'red'"
[circleDraggable]="true"
[editable]="true">
</sebm-google-map-circle>
</sebm-google-map>
app.component.ts
import { Component } from '#angular/core';
import { GeoService } from './GeoService';
#Component({
selector: 'my-app',
moduleId: module.id,
templateUrl: `./app.component.html`,
styleUrls: ['/app.componenet.css'],
providers :[GeoService]
})
export class AppComponent {
title = 'Angular2 google map test';
lat: number = 51.673858;
lng: number = 7.815982;
zoom: number = 8;
markers: marker[] = [
{
lat: 51.673858,
lng: 7.815982,
label: 'A',
draggable: true
},
{
lat: 51.373858,
lng: 7.215982,
label: 'B',
draggable: false
},
{
lat: 51.723858,
lng: 7.895982,
label: 'C',
draggable: true
}
];
location: string;
findLocation(): void {
this.result= this.geoService.getLocation(this.location);
}
constructor(private geoService: GeoService) {
}
clickedMarker(label: string, index: number) {
}
mapClicked($event: MouseEvent) {
}
markerDragEnd(m: marker, $event: MouseEvent) {
console.log('dragEnd', m, $event);
}
}
// tslint:disable-next-line:class-name
interface marker {
lat: number;
lng: number;
label?: string;
draggable: boolean;
}
how to get the result in app.component.ts?
findLocation(): void {
this.result= this.geoService.getLocation(this.location);
}
Hopefully you are not still stuck on this. While this might no longer help you, hopefully it will help someone else. Here is what I did just now. First change the getLocation function to this. This is for the current Angular2 release.
getLocation(term: string):Promise<any> {
return this.http.get('http://maps.google.com/maps/api/geocode/json?address=' + term + 'CA&sensor=false')
.toPromise()
.then((response) => Promise.resolve(response.json()));
.catch((error) => Promise.resolve(error.json()));
}
And then in app.component.ts, change it to this.
findLocation(): void {
this.geoService.getLocation(this.location)
.then((response) => this.result = response.results[0])
.catch((error) => console.error(error));
}
I added some error control because that is always good to have. And I had a results array return inside response so clarify with the user which address they want if there is more than one returned.
angular 7.1.4 httpclient is used. getLocation returns obserable
location.service.ts renamed GeoService.ts
import { Injectable } from "#angular/core";
import { HttpClient } from "#angular/common/http";
import { Observable } from "rxjs";
#Injectable({
providedIn: "root"
})
export class LocationService {
constructor(private http: HttpClient) {}
getLocation(term: string): Observable<any> {
return this.http.get(
"http://maps.google.com/maps/api/geocode/json?address=" +
term +
"CA&sensor=false&key=API_KEY"
);
}
}
location.component.ts
/// <reference types="#types/googlemaps" />
import { Component, OnInit, AfterContentInit, ViewChild } from "#angular/core";
import { LocationService } from "../location.service";
declare let google: any;
#Component({
selector: "app-location",
templateUrl: "./location.component.html",
styleUrls: ["./location.component.scss"],
providers: [LocationService]
})
export class LocationComponent implements OnInit {
#ViewChild("gmap") gmapElement: any;
map: google.maps.Map;
latitude: number;
longitude: number;
marker: google.maps.Marker;
locationStr: string;
public result: any;
countMarkers = 0;
constructor(public geoService: LocationService) {}
ngOnInit() {
this.setCurrentPosition();
// tslint:disable-next-line:prefer-const
let mapProp = {
center: new google.maps.LatLng(0, 0),
zoom: 18,
mapTypeId: google.maps.MapTypeId.ROADMAP,
disableDefaultUI: true
};
this.map = new google.maps.Map(this.gmapElement.nativeElement, mapProp);
}
setCenter(e: any) {
e.preventDefault();
this.map.setCenter(new google.maps.LatLng(this.latitude, this.longitude));
}
setCurrentPosition() {
navigator.geolocation.getCurrentPosition(position => {
console.log("Set position", position.coords);
this.latitude = position.coords.latitude;
this.longitude = position.coords.longitude;
this.map.setCenter(new google.maps.LatLng(this.latitude, this.longitude));
const location = new google.maps.LatLng(this.latitude, this.longitude);
this.map.panTo(location);
if (!this.marker) {
this.marker = new google.maps.Marker({
position: location,
map: this.map,
draggable: false,
title: "You Loation!"
});
this.marker.setLabel("You");
this.marker.setMap(this.map);
} else {
this.marker.setPosition(location);
}
});
}
setMarker(label = ".") {
const location = new google.maps.LatLng(this.latitude, this.longitude);
this.map.panTo(location);
if (!this.marker) {
this.marker = new google.maps.Marker({
position: location,
map: this.map,
draggable: false,
title: "You Loation!"
});
this.marker.setLabel(label);
this.marker.setMap(this.map);
} else {
this.marker.setLabel(label);
this.marker.setPosition(location);
}
}
addMarker(label = "") {
const location = new google.maps.LatLng(this.latitude, this.longitude);
// this.map.panTo(location);
const newMarker = new google.maps.Marker({
position: location,
map: this.map,
draggable: false,
title: "You Loation!"
});
this.countMarkers++;
label = this.countMarkers.toString();
newMarker.setLabel(label);
newMarker.setMap(this.map);
}
findLocation(): void {
this.geoService
.getLocation(this.locationStr)
.subscribe(
(data: any) => (
(this.result = data.results[0].geometry.location),
console.log(data.results[0].geometry.location),
(this.latitude = data.results[0].geometry.location.lat),
(this.longitude = data.results[0].geometry.location.lng),
this.map.setCenter(
new google.maps.LatLng(this.latitude, this.longitude)
),
this.addMarker()
),
(err: any) => console.log(err),
() => console.log("All done getting location.")
);
}
}