【问题标题】:Google Maps Places Autocomplete - Uncaught TypeError: Cannot read property 'getPlace' of undefinedGoogle Maps Places Autocomplete - Uncaught TypeError:无法读取未定义的属性“getPlace”
【发布时间】:2016-09-10 21:13:23
【问题描述】:
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>

我有这些函数,它们应该从输入字段(originInput 和destinationPlaceInput)向我提供从 Google Maps Places 到 A 到 B 的方向。

选择输入后,控制台中出现此错误:

未捕获的类型错误:无法读取未定义的属性“getPlace”

在“place_changed”事件触发后抛出此错误。

【问题讨论】:

    标签: angularjs google-maps maps google-places-api angular-google-maps


    【解决方案1】:

    place_changed-callback 中,关键字this 指向已触发事件的对象。

    所以你可以简单地使用

    var place = this.getPlace();
    

    而不是

    var place = this.destinationAutocomplete.getPlace();
    

    【讨论】:

    • 谢谢。逻辑 101。我想我有点累了。
    【解决方案2】:

    如何保留控制器的上下文/this

    tldr:

    创建一个返回带有上下文的函数的函数:

    this.searchBox.addListener('places_changed', ((that) => () => this.placesChanged(that))(this));
    

    说明

    正如Dr.Molle 指出的那样:this 指向触发了事件的对象,即您要在其上添加事件监听器的元素。

    addListener 接受一个函数声明。要保持对控制器的 this 的访问,您还可以创建一个闭包,将控制器的 this 传递给函数,如下所示:

    this.searchBox.addListener('places_changed', ((that) => () => this.placesChanged(that))(this));
    

    在这里我定义了一个函数,它接受一个名为that 的参数,并在执行时返回一个包含 this 的函数。它是一个闭包,因为内部函数的作用域保留了对外部函数作用域中that 变量的引用(以及可以传递给this.placesChanged 的其他变量)。

    现在,如果发出事件places_changed,则运行函数声明。我仍然能够更改this.placesChanged 函数内that 变量的属性。这是可能的,因为对象是通过引用传递的(而原始类型是通过值传递的)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-16
      • 2021-04-28
      • 2017-07-20
      • 1970-01-01
      • 2020-03-28
      • 2023-04-11
      相关资源
      最近更新 更多