Reputation: 415
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)}};
Upvotes: 4
Views: 3765
Reputation: 19
I hope this helps. I converted all the relavent types to typescript for a recent project.
Also, as you can see in my application's backend a custom url is appended to the PlaceResult so I'm extending the type for my usecase using an interface.
// docs: https://developers.google.com/maps/documentation/places/web-service/search-nearby#nearby-search-responses
export interface RRPlaceResult extends PlaceResult {
url: string;
}
export type PlaceResult = {
html_attributions: string[];
results: Place[];
status: PlacesSearchStatus;
error_message?: string;
info_messages?: string[];
next_page_token?: string;
};
export type Place = {
address_components?: AddressComponent[];
adr_adress?: string;
business_status?: string;
curbside_pickup?: boolean;
current_opening_hours?: PlaceOpeningHours;
delivery?: boolean;
dine_in?: boolean;
editorial_summary?: PlaceEditorialSummary;
formatted_address?: string;
formatted_phone_number?: string;
geometry?: Geometry;
icon?: string;
icon_background_color?: string;
icon_mask_base_uri?: string;
international_phone_number?: string;
name?: string;
opening_hours?: PlaceOpeningHours;
permanently_closed?: boolean; // deprecated
photos?: PlacePhoto[];
place_id?: string;
plus_code?: PlusCode;
price_level?: number;
rating?: number;
reference?: string; // deprecated
reservable?: boolean;
reviews?: PlaceReview[];
scope?: string; //deprecated
secondary_opening_hours?: PlaceOpeningHours[];
serves_beer?: boolean;
serves_breakfast?: boolean;
serves_brunch?: boolean;
serves_dinner?: boolean;
serves_lunch?: boolean;
serves_vegetarian_food?: boolean;
serves_wine?: boolean;
takeout?: boolean;
types?: string[];
url?: string;
user_ratings_total?: number;
utc_offset?: number;
vicinity?: string;
website?: string;
wheelchair_accessible_entrance?: boolean;
};
export type PlacesSearchStatus = 'OK' | 'ZERO_REULTS' |
'INVALID_REQUEST' | 'OVER_QUERY_LIMIT' | 'REQUEST_DENIED' |
'UNKNOWN_ERROR';
export type AddressComponent = {
long_name: string;
short_name: string;
types: string[];
};
export type PlaceEditorialSummary = {
language?: string;
overview?: string;
};
export type Geometry = {
location: LatLngLiteral;
viewport: Bounds;
};
export type LatLngLiteral = {
lat: number;
lng: number;
};
export type Bounds = {
northeast: LatLngLiteral;
southwest: LatLngLiteral;
};
export type PlaceOpeningHours = {
open_now?: boolean;
periods?: PlaceOpeningHoursPeriod[];
special_days?: PlaceSpecialDay[];
type?: string;
weekday_text?: string[];
};
export type PlaceOpeningHoursPeriod = {
open: PlaceOpeningHoursPeriodDetail;
close?: PlaceOpeningHoursPeriodDetail;
};
export type PlaceSpecialDay = {
date?: string;
exceptional_hours?: boolean;
};
export type PlaceOpeningHoursPeriodDetail = {
day: number;
time: string;
date?: string;
truncated?: boolean;
};
export type PlacePhoto = {
height: number;
html_attributions: string[];
photo_reference: string;
width: number;
};
export type PlusCode = {
global_code: string;
compound_code?: string;
};
export type PlaceReview = {
author_name: string;
rating: number;
relative_time_description: string;
time: number;
author_url?: string;
language?: string;
original_language?: string;
profile_photo_url?: string;
text?: string;
translated?: boolean;
};
Upvotes: 0
Reputation: 11
I just wanted to give an update to this answer. I am using this code in a application written in Ionic which is a Angular based library. I was able to use this code and get it to work but I had to change one thing. The infowindow would not open and kept throwing the Uncaught TypeError: this.b.getElementsByTagName is not a function
error. In order to fix this I had to change
google.maps.event.addListener(marker, 'click', () => {
this.ngZone.run(() => {
infowindow.setContent(place.name);
infowindow.open(this.map,this);
});
to
google.maps.event.addListener(marker, 'click', () => {
this.ngZone.run(() => {
infowindow.setContent(place.name);
infowindow.open(this.map,this.infowindow);
});
adding
this.infowindow
was the key. Hope this helps someone who ran into the same problem as me
Upvotes: 1
Reputation: 71911
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);
});
});
}
}
Upvotes: 4