问题
setAutocomplete() {
this.originPlaceId = null;
this.destinationPlaceId = null;
this.travelMode = google.maps.TravelMode.WALKING;
this.directionsDisplay.setMap(this.map);
this.setMapControls(this.map);
this.setupClickListener('changemode-walking', google.maps.TravelMode.WALKING);
this.setupClickListener('changemode-transit', google.maps.TravelMode.TRANSIT);
this.setupClickListener('changemode-driving', google.maps.TravelMode.DRIVING);
console.log(this.originInput);
this.originAutocomplete = new google.maps.places.Autocomplete(this.originInput);
this.originAutocomplete.bindTo('bounds', this.map);
console.log(this.originAutocomplete);
this.originAutocomplete.addListener('place_changed', function() {
console.log(this.originAutocomplete);
var place = this.originAutocomplete.getPlace();
console.log("here", place);
if (!place.geometry) {
window.alert("Autocomplete's returned place contains no geometry");
return;
}
this.expandViewportToFitPlace(this.map, place);
// If the place has a geometry, store its place ID and route if we have
// the other place ID
this.originPlaceId = place.place_id;
this.route(this.directionsService, this.directionsDisplay);
});
this.destinationAutocomplete = new google.maps.places.Autocomplete(this.destinationPlaceInput);
this.destinationAutocomplete.bindTo('bounds',this.map);
this.destinationAutocomplete.addListener('place_changed', function() {
var place = this.destinationAutocomplete.getPlace();
if (!place.geometry) {
window.alert("Autocomplete's returned place contains no geometry");
return;
}
this.expandViewportToFitPlace(this.map, place);
// If the place has a geometry, store its place ID and route if we have
// the other place ID
this.destinationPlaceId = place.place_id;
this.route(this.directionsService, this.directionsDisplay);
//this.getNearbyPlaces(this.destinationPlaceId, 5000);
});
};
setMapControls(map) {
this.originInput = document.getElementById('origin-input');
this.destinationPlaceInput = document.getElementById('destination-input');
this.modes = document.getElementById('mode-selector');
map.controls[google.maps.ControlPosition.TOP_LEFT].push(this.originInput);
map.controls[google.maps.ControlPosition.TOP_LEFT].push(this.destinationPlaceInput);
map.controls[google.maps.ControlPosition.TOP_LEFT].push(this.modes);
};
<input id="origin-input" class="controls" type="text" force-selection="true" placeholder="Enter an origin location">
<input id="destination-input" class="controls" type="text" force-selection="true" placeholder="Enter a destination location">
<div id="mode-selector" class="controls">
<input type="radio" name="type" id="changemode-walking" checked="checked">
<label for="changemode-walking">Walking</label>
<input type="radio" name="type" id="changemode-transit">
<label for="changemode-transit">Transit</label>
<input type="radio" name="type" id="changemode-driving">
<label for="changemode-driving">Driving</label>
</div>
<div id="directionsList"></div>
<div id="map_canvas"></div>
I have these functions which are supposed to give me the directions A to B from Google Maps Places from the input fields (originInput and destinationPlaceInput).
After I select an input I have this error in console:
Uncaught TypeError: Cannot read property 'getPlace' of undefined
This error is thrown after the "place_changed" event triggers.
回答1:
Inside the place_changed
-callback the keyword this
points to the object which has been triggered the event.
so you may simply use
var place = this.getPlace();
instead of
var place = this.destinationAutocomplete.getPlace();
回答2:
How to keep the context/this
of the controller?
tldr:
Create a function that returns a function with the context:
this.searchBox.addListener('places_changed', ((that) => () => this.placesChanged(that))(this));
Explanation
Like Dr.Molle points out: this
points to the object which has triggered the event, namely the element on which you want to add an event listener on.
The addListener takes a function declaration. To keep access on your controller's this
, you could also create a closure that passes the controller's this
into the function, like so:
this.searchBox.addListener('places_changed', ((that) => () => this.placesChanged(that))(this));
Here I defined a function that takes a parameter called that
, and upon execution returns a function that contains the this. It is a closure because the inner function's scope keeps a reference to the that
variable from the outer functions scope (and other variables that could get passed to this.placesChanged
).
Now if a event places_changed
is emitted, the function declaration is ran. I am still able to change properties on the that
variable inside the this.placesChanged
function. This is possible because in objects are passed by reference (whereas primitive types are passed by values).
来源:https://stackoverflow.com/questions/37230901/google-maps-places-autocomplete-uncaught-typeerror-cannot-read-property-getp