Search code examples
angulartypescriptionic-frameworkionic2google-places-api

Google Places API - Angular 2 / Typescript / Ionic 2


Has anyone ever converted this is into typescript?

  var map;
  var infowindow;

  function initMap() {
    var pyrmont = {lat: -33.867, lng: 151.195};

    map = new google.maps.Map(document.getElementById('map'), {
      center: pyrmont,
      zoom: 15
    });

    infowindow = new google.maps.InfoWindow();
    var service = new google.maps.places.PlacesService(map);
    service.nearbySearch({
      location: pyrmont,
      radius: 500,
      type: ['store']
    }, callback);
  }

  function callback(results, status) {
    if (status === google.maps.places.PlacesServiceStatus.OK) {
      for (var i = 0; i < results.length; i++) {
        createMarker(results[i]);
      }
    }
  }

  function createMarker(place) {
    var placeLoc = place.geometry.location;
    var marker = new google.maps.Marker({
      map: map,
      position: place.geometry.location
    });

    google.maps.event.addListener(marker, 'click', function() {
      infowindow.setContent(place.name);
      infowindow.open(map, this);
    });
  }

I have tried to convert it myself as seen below but I am getting an error in console that I will show below the code, If anyone could give a heads up where im going wrong it would be great

  constructor(public navCtrl: NavController, private navParams: NavParams, private ngZone: NgZone) {}

  ionViewDidLoad() {
    console.log('ionViewDidLoad DetailsPage');
    this.loadMap();
  }

  @ViewChild('map') mapElement: ElementRef;
  map: any;

  loadMap(){

    Geolocation.getCurrentPosition().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(this.mapElement.nativeElement, mapOptions);

      let service = new google.maps.places.PlacesService(mapOptions);

      service.nearbySearch({
        location: latLng,
        radius: 500,
        type: ['pub']
      }, (results, status) => {
          this.callback(results, status)
      });

    }, (err) => {
      console.log(err);
    });

  }

  callback(results, status) {
    if (status === google.maps.places.PlacesServiceStatus.OK) {
      for (var i = 0; i < results.length; i++) {
        this.createMarker(results[i]);
      }
    }
  }

  createMarker(place){
    var placeLoc = place.geometry.location;
    var marker = new google.maps.Marker({
        map: this.map,
        position: place.geometry.location
    });

    let infowindow = new google.maps.InfoWindow();

    google.maps.event.addListener(marker, 'click', () => {
      this.ngZone.run(() => {
        infowindow.setContent(place.name);
        infowindow.open(this.map,this);
      });
    });
  }

  addMarker(){

    let marker = new google.maps.Marker({
      map: this.map,
      animation: google.maps.Animation.DROP,
      position: this.map.getCenter()
    });

    let content = "<h4>You are here!</h4>";          

    this.addInfoWindow(marker, content);

  }

  addInfoWindow(marker, content){

    let infoWindow = new google.maps.InfoWindow({
      content: content
    });

    google.maps.event.addListener(marker, 'click', () => {
      this.ngZone.run(() => {
        infoWindow.open(this.map, marker);
      });
    });
  }

error in console

Uncaught TypeError: this.b.getElementsByTagName is not a function
    at B5.attributionText_changed (places_impl.js:28)
    at zb (js?key=AIzaSyAZTATsl9JjVKodXRnzeSk52Ndvtz-HPPU&libraries=places:36)
    at B5._.y.bindTo (js?key=AIzaSyAZTATsl9JjVKodXRnzeSk52Ndvtz-HPPU&libraries=places:104)
    at Object.f6.f (places_impl.js:38)
    at Hw.<anonymous> (js?key=AIzaSyAZTATsl9JjVKodXRnzeSk52Ndvtz-HPPU&libraries=places:137)
    at js?key=AIzaSyAZTATsl9JjVKodXRnzeSk52Ndvtz-HPPU&libraries=places:105
    at Object.<anonymous> (js?key=AIzaSyAZTATsl9JjVKodXRnzeSk52Ndvtz-HPPU&libraries=places:37)
    at js?key=AIzaSyAZTATsl9JjVKodXRnzeSk52Ndvtz-HPPU&libraries=places:105
    at js?key=AIzaSyAZTATsl9JjVKodXRnzeSk52Ndvtz-HPPU&libraries=places:37
    at js?key=AIzaSyAZTATsl9JjVKodXRnzeSk52Ndvtz-HPPU&libraries=places:105

Specifically as highlighted in console file.

b.getElementsByTagName("a"),c=0;c<_.w(b);c++)b[c].style.color="#444";this.H&&this.H.set("placesDataProviders",a)};B5.prototype.hide_changed=function(){_.kA(this.b,!this.get("hide"))};_.t(D5,_.y);_.k=D5.prototype;_.k.input_changed=function(){window.clearTimeout(this.f);this.f=window.setTimeout((0,_.p)(this.Ol,this),100)};_.k.Ol=function(){var a=this.l,b=this.Lb();a!=b&&(H5(this),this.l=b);this.f=null};_.k.Jm=function(){if(this.Tc())J5(this,this.Lb());else{var a={name:this.Lb()};this.Ef(a)}};

Solution

  • The this context is lost if you add a callback function like that. There are multiple ways to solve this. One is to use an anonymous function wrapper:

    service.nearbySearch({
      location: latLng,
      radius: 500,
      type: ['pub']
    }, (results, status) => {
      this.callback(results, status);
    });
    

    Also be aware that a change detection cycle is not triggered when you use the addListener calls from google.maps. Check this answer for more information. You might run into that problem with your addInfoWindow function:

    @Component({
        selector : 'maps-test',
        template : '<div #map></div>'
    })
    export class MapsTestComponent {
    
      @ViewChild('map')
      mapElement: ElementRef;
    
      constructor(private ngZone: NgZone){}
    
      ngAfterViewInit() {
          loadMap();
      }
    
      loadMap(){
    
        Geolocation.getCurrentPosition().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(this.mapElement.nativeElement, mapOptions);
    
                let service = new google.maps.places.PlacesService(this.map);
    
    
          service.nearbySearch({
            location: latLng,
            radius: 500,
            type: ['pub']
          }, (results, status) => {
              this.callback(results, status)
          });
    
        }, (err) => {
          console.log(err);
        });
    
      }
    
      callback(results, status) {
        if (status === google.maps.places.PlacesServiceStatus.OK) {
          for (var i = 0; i < results.length; i++) {
            this.createMarker(results[i]);
          }
        }
      }
    
      createMarker(place){
        var placeLoc = place.geometry.location;
        var marker = new google.maps.Marker({
            map: this.map,
            position: place.geometry.location
        });
    
        let infowindow = new google.maps.InfoWindow();
    
        google.maps.event.addListener(marker, 'click', () => {
          this.ngZone.run(() => {
            infowindow.setContent(place.name);
            infowindow.open(this.map,this);
          });
        });
      }
    
      addMarker(){
    
        let marker = new google.maps.Marker({
          map: this.map,
          animation: google.maps.Animation.DROP,
          position: this.map.getCenter()
        });
    
        let content = "<h4>You are here!</h4>";          
    
        this.addInfoWindow(marker, content);
    
      }
    
      addInfoWindow(marker, content){
    
        let infoWindow = new google.maps.InfoWindow({
          content: content
        });
    
        google.maps.event.addListener(marker, 'click', () => {
          this.ngZone.run(() => {
            infoWindow.open(this.map, marker);
          });
        });
      }
    }