X
    Categories: Angularjs 2

google map directions display in angular 2

Google map directions display in angular 2

Goole map directions display using angular 2 with typescript. Normally google map providing Directions Service in javascript. We need to convert it to for angular 2.
Here you can see how to integrate google map in angular 2 with typescript. Lets see how to display google map directions in angular 2

Step 1 :

Integrate Google Map

Find a tutorial @ http://www.17educations.com/angularjs-2/google-map-api-angular-2-typescript/

Step 2 :

Add direction display tag inside sebm-google-map tag at your template

Eg :  <sebm-google-map-directions [origin]=”origin” [destination]=”destination”></sebm-google-map-directions>

Step 3 :

Create custom Directory to Display Direction.  Here my Directive Name is DirectionsMapDirective.

Step 4 :

Import your Directory and Merge it with declarations in your module file.

Step 5 :

Integrate your directive with components to display your google map directions.

 

Example Source Code:

Custom Directive => DirectionsMapDirective
My directive path is app/map/googlr-map.directive.ts

import {GoogleMapsAPIWrapper}  from 'angular2-google-maps/core';
import { Directive,  Input, Output } from '@angular/core';


declare var google: any;



@Directive({
  selector: 'sebm-google-map-directions'
})
export class DirectionsMapDirective {
  @Input() origin:any ;
  @Input() destination:any;
  @Input() originPlaceId:any;
  @Input() destinationPlaceId:any;
  @Input() waypoints:any;
  @Input() directionsDisplay:any;
  @Input() estimatedTime : any;
  @Input() estimatedDistance : any;
 
  constructor (private gmapsApi: GoogleMapsAPIWrapper) {}
  updateDirections(){
    this.gmapsApi.getNativeMap().then(map => {
              if(!this.originPlaceId || !this.destinationPlaceId ){
                return;
              }
              
              var directionsService = new google.maps.DirectionsService;
              var me = this;
              var latLngA = new google.maps.LatLng({lat: this.origin.latitude, lng: this.origin.longitude });
              var latLngB = new google.maps.LatLng({lat: this.destination.latitude, lng: this.destination.longitude });
              this.directionsDisplay.setMap(map);
              this.directionsDisplay.setOptions({
                polylineOptions: {
                            strokeWeight: 8,
                            strokeOpacity: 0.7,
                            strokeColor:  '#00468c' 
                        }
                });
              this.directionsDisplay.setDirections({routes: []});
              directionsService.route({
                      origin: {placeId : this.originPlaceId },
                      destination: {placeId : this.destinationPlaceId },
                      avoidHighways: true,
                      travelMode: google.maps.DirectionsTravelMode.DRIVING
                      //travelMode: 'DRIVING'
                    }, function(response: any, status: any) {
                                if (status === 'OK') {
                                  me.directionsDisplay.setDirections(response);
                                  map.setZoom(30);
                                  //console.log(me.getcomputeDistance (latLngA, latLngB));
                                  var point = response.routes[ 0 ].legs[ 0 ];
                                  me.estimatedTime = point.duration.text ;
                                  me.estimatedDistance = point.distance.text;
                                  console.log(me.estimatedTime);
                                  console.log( 'Estimated travel time: ' + point.duration.text + ' (' + point.distance.text + ')' );
 
                                } else {
                                  console.log('Directions request failed due to ' + status);
                                }
              });
    });

  }

  private getcomputeDistance(latLngA: any , latLngB: any ) 
  {
    return (google.maps.geometry.spherical.computeDistanceBetween(latLngA, latLngB) / 1000).toFixed(2);
  }
}

Import in your module. app.module.ts

import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AgmCoreModule } from "angular2-google-maps/core";
import { FormControl, FormsModule, ReactiveFormsModule } from "@angular/forms";

import { DirectionsMapDirective } from './map/google-map.directive';

import { AppComponent }  from './app.component';

@NgModule({
  imports:      [ 
  		AgmCoreModule.forRoot({
     		 	apiKey: "************************",
     		 	libraries: ["places"]
    			}),
  		BrowserModule,
  		FormsModule,
  		ReactiveFormsModule
  		],
  declarations: [ AppComponent, DirectionsMapDirective ],
  bootstrap:    [ AppComponent ]
})
export class AppModule { }

Replace ******* with your map api key @apiKey field

My app.component.ts will be.

import { Component, NgModule, NgZone, OnInit, ViewChild, ElementRef, Directive, Input  } from '@angular/core';
import { FormControl, FormsModule, ReactiveFormsModule } from "@angular/forms";
import { BrowserModule } from "@angular/platform-browser";
import { AgmCoreModule, MapsAPILoader, GoogleMapsAPIWrapper } from 'angular2-google-maps/core';
import { DirectionsMapDirective } from './map/google-map.directive';

declare var google:any;
declare var jQuery:any;

@Component({
  selector: 'my-app',
   styles: [`
    .sebm-google-map-container {
       height: 300px;
     },
     
  `],
template: `
    <div class="container">
      <h1>Angular 2 Google Map Direction Display</h1>
      <div class="form-group">
        <input placeholder="Enter source location" autocorrect="off" autocapitalize="off" spellcheck="off" type="text" class="form-control" #pickupInput [formControl]="destinationInput">
        <input placeholder="Enter destination" autocorrect="off" autocapitalize="off" spellcheck="off" type="text" class="form-control" #pickupOutput [formControl]="destinationOutput" >
      </div>
       <sebm-google-map [latitude]="latitude" [longitude]="longitude" [scrollwheel]="false" [zoom]="zoom" [styles]="mapCustomStyles">
                <!-- <sebm-google-map-marker [latitude]="latitude" [longitude]="longitude" [iconUrl]="iconurl">
                    <sebm-google-map-info-window>
                        <strong>InfoWindow content</strong>
                    </sebm-google-map-info-window>
                </sebm-google-map-marker> -->
                <sebm-google-map-directions [origin]="origin" [destination]="destination"></sebm-google-map-directions>
              </sebm-google-map>
    </div>
  `,
 providers : [ GoogleMapsAPIWrapper ]
})

export class AppComponent implements OnInit {
    public latitude: number;
    public longitude: number;
    public destinationInput: FormControl;
    public destinationOutput: FormControl;
    public zoom: number;
    public iconurl: string;
    public mapCustomStyles : any;
    public estimatedTime: any;
    public estimatedDistance: any;

    @ViewChild("pickupInput")
    public pickupInputElementRef: ElementRef;

     @ViewChild("pickupOutput")
    public pickupOutputElementRef: ElementRef;

     @ViewChild("scrollMe")
    private scrollContainer: ElementRef;

    @ViewChild(DirectionsMapDirective) vc: DirectionsMapDirective;

    public origin :any ; // its a example aleatory position
    public destination : any; // its a example aleatory position
    constructor(
      private mapsAPILoader: MapsAPILoader,
      private ngZone: NgZone,
      private gmapsApi: GoogleMapsAPIWrapper,
      private _elementRef : ElementRef
    ) {
    }
    
    ngOnInit() {
      //set google maps defaults
      this.zoom = 4;
      this.latitude = 39.8282;
      this.longitude = -98.5795;
      //this.iconurl = '../image/map-icon.png';
      this.iconurl = '../image/map-icon.png';

     // this.mapCustomStyles = this.getMapCusotmStyles();
      //create search FormControl
      this.destinationInput = new FormControl();
      this.destinationOutput = new FormControl();
      //set current position
      this.setCurrentPosition();
      
      //load Places Autocomplete
      this.mapsAPILoader.load().then(() => {
          let autocompleteInput = new google.maps.places.Autocomplete(this.pickupInputElementRef.nativeElement, {
            types: ["address"]
          });

          let autocompleteOutput = new google.maps.places.Autocomplete(this.pickupOutputElementRef.nativeElement, {
            types: ["address"]
          });
        
                 this.setupPlaceChangedListener(autocompleteInput, 'ORG');
                this.setupPlaceChangedListener(autocompleteOutput, 'DES');
      });
    }
    
    private setupPlaceChangedListener(autocomplete: any, mode: any ) {
      autocomplete.addListener("place_changed", () => {
            this.ngZone.run(() => {
              //get the place result
              let place: google.maps.places.PlaceResult = autocomplete.getPlace();
              //verify result
              if (place.geometry === undefined) {
                return;
              }
              if (mode === 'ORG') {
                  this.vc.origin = { longitude: place.geometry.location.lng(), latitude: place.geometry.location.lat() }; 
                  this.vc.originPlaceId = place.place_id;
              } else {
                  this.vc.destination = { longitude: place.geometry.location.lng(), latitude: place.geometry.location.lat() }; // its a example aleatory position
                  this.vc.destinationPlaceId = place.place_id;
              }
  
              if(this.vc.directionsDisplay === undefined){ this.mapsAPILoader.load().then(() => { 
                    this.vc.directionsDisplay = new google.maps.DirectionsRenderer;
                  }); 
            }
          
              //Update the directions
              this.vc.updateDirections();
              this.zoom = 12;
            });

         });

    }

    getDistanceAndDuration(){
      this.estimatedTime = this.vc.estimatedTime;
      this.estimatedDistance = this.vc.estimatedDistance;
    }

    scrollToBottom(): void {
      jQuery('html, body').animate({ scrollTop: jQuery(document).height() }, 3000);
    }
    private setPickUpLocation( place:any ) {
      //verify result
            if (place.geometry === undefined || place.geometry === null) {
              return;
            }
            //set latitude, longitude and zoom
            this.latitude = place.geometry.location.lat();
            this.longitude = place.geometry.location.lng();
            this.zoom = 12;
    }

    private setCurrentPosition() {
      if ("geolocation" in navigator) {
        navigator.geolocation.getCurrentPosition((position) => {
          this.latitude = position.coords.latitude;
          this.longitude = position.coords.longitude;
          this.zoom = 12;
        });
      }
    }

    private getMapCusotmStyles() {
      // Write your Google Map Custom Style Code Here.
    }

}

 

 

Hope it will Help someone also.

You can find more discussions about google map directions at https://github.com/SebastianM/angular2-google-maps/issues/495

Marimuthu:

View Comments

  • Hello, how could you modify the code so that you could also add the origin and destination marker directly from the map

  • Very helpful guide but for the life of me I cannot get my old map to clear when changing the directions. Any ideas?

  • I am facing some issue can you please help me out ?

    Can't bind to 'latitude' since it isn't a known property of 'sebm-google-map'.

  • Excellent guide managed to get this working but having problems getting the estimatedTime and estimatedDistance back from the directive it seems to be a timing issue as this is not calculated until after directionsService.route() but if I console.log the esstimatedTime in my parent component it is undefined. Any ideas

  • Hello. thanks for this tuguide. I just copied your code, but I get error on this code
    let place: google.maps.places.PlaceResult = autocomplete.getPlace();

    it says Cannot find namespace 'google'. is it OK for angular 5?
    i am using angular 5.

    • i am facing same problem and here i didn't get any html code. can you provide for me
      - Thanks in advance

        • In your code you are using origin, destination
          "origin: {lat: this.origin.latitude, lng: this.origin.longitude},
          destination: {lat: this.destination.latitude, lng: this.destination.longitude}"
          but in my code i have origin and destination like
          ----------------------------------------------------------------
          app.component.ts
          ---------------
          markers: marker[] = [
          { lat: 51.673858,
          lng: 7.815982,
          label: 'A',
          draggable: true },
          { lat: 51.373858,
          lng: 7.215982,
          label: 'B',
          draggable: false }, ]

          How can i overcome this is issue, can you plese helpme out to overcome this.

        • i have two point in my map how can i get direction bewteen that two points, I am putting my code here
          component.ts
          ------------------
          import { Component } from '@angular/core';
          import { MouseEvent } from '@agm/core';
          import { DirectionsMapDirective } from './directiondirective';
          @Component({
          selector: 'app-root',
          templateUrl: './app.component.html',
          styleUrls: [ './app.component.css' ]
          })
          export class AppComponent {
          zoom: number = 8;
          lat: number = 51.673858;
          lng: number = 7.815982;
          markers: marker[] = [
          {
          lat: 51.673858,
          lng: 7.815982,
          label: 'A',
          draggable: true
          },
          {
          lat: 51.373858,
          lng: 7.215982,
          label: 'B',
          draggable: false
          }
          ]
          }
          interface marker {
          lat: number;
          lng: number;
          label?: string;
          draggable: boolean;
          }

          • i have created a pastebin for example. after u make it work to ur project, u can just do something like this

          • Check My above Directive "google-map.directive.ts". If you added your directive corretly for "sebm-google-map-directions" element, Then you will not face this error.

          • Directive.ts
            --------------------
            import {GoogleMapsAPIWrapper} from '@agm/core';
            import { Directive, Input, Output } from '@angular/core';

            declare var google: any;

            @Directive({
            selector: 'agm-map'
            })
            export class DirectionsMapDirective {
            @Input() origin:any ;
            @Input() destination:any;
            @Input() originPlaceId:any;
            @Input() destinationPlaceId:any;
            @Input() waypoints:any;
            @Input() directionsDisplay:any;
            @Input() estimatedTime : any;
            @Input() estimatedDistance : any;

            constructor (private gmapsApi: GoogleMapsAPIWrapper) {}
            updateDirections(){
            this.gmapsApi.getNativeMap().then(map => {
            if(!this.originPlaceId || !this.destinationPlaceId ){
            return;
            }

            var directionsService = new google.maps.DirectionsService;
            var me = this;
            var latLngA = new google.maps.LatLng({lat: this.origin.latitude, lng: this.origin.longitude });
            var latLngB = new google.maps.LatLng({lat: this.destination.latitude, lng: this.destination.longitude });
            this.directionsDisplay.setMap(map);
            this.directionsDisplay.setOptions({
            polylineOptions: {
            strokeWeight: 8,
            strokeOpacity: 0.7,
            strokeColor: '#00468c'
            }
            });
            this.directionsDisplay.setDirections({routes: []});
            directionsService.route({
            origin: {placeId : this.originPlaceId },
            destination: {placeId : this.destinationPlaceId },
            avoidHighways: true,
            travelMode: google.maps.DirectionsTravelMode.DRIVING
            //travelMode: 'DRIVING'
            }, function(response: any, status: any) {
            if (status === 'OK') {
            me.directionsDisplay.setDirections(response);
            map.setZoom(30);
            //console.log(me.getcomputeDistance (latLngA, latLngB));
            var point = response.routes[ 0 ].legs[ 0 ];
            me.estimatedTime = point.duration.text ;
            me.estimatedDistance = point.distance.text;
            console.log(me.estimatedTime);
            console.log( 'Estimated travel time: ' + point.duration.text + ' (' + point.distance.text + ')' );

            } else {
            console.log('Directions request failed due to ' + status);
            }
            });
            });

            }

            private getcomputeDistance(latLngA: any , latLngB: any )
            {
            return (google.maps.geometry.spherical.computeDistanceBetween(latLngA, latLngB) / 1000).toFixed(2);
            }
            }
            component.ts
            ------------------

            This is the occation i am getting that error what i mentined above

          • i am using another directive for my requirment and using "sebm-google-map-directions" element in html, that is the reason i am getting this can you tell me the reason.

          • make sure the direction directive works and check if the direction directive file is inside app directory. thats all u need.

          • i think u should change ur code from lat => latitude and lng => longitude to make it work. or u can edit my code to lat and lng

        • Here i have two points by default(origin, destination)
          1) I have two points by default
          2) I need service for directions between that two points
          3) In that i don't need of autocomplete of places/ names in it
          for example : when i am trying to enter a city name i don't need dropdown / options over there.
          Can anyone have related to this requirement please post it.
          -Thank you in advance

  • Here i have two points by default(origin, destination)
    1) I have two points by default
    2) I need service for directions between that two points
    3) In that i don't need of autocomplete of places/ names in it
    for example : when i am trying to enter a city name i don't need dropdown / options over there.
    Can anyone have related to this requirement please post it.
    -Thank you in advance

  • Hi,
    in UpdateDirection - console.log -- printing correct estimated date and time and distance, but inside component im not able to get it printed. it prints the old one, not in sync, how to print in component HTML also. please help.