无效值错误:不是HTMLInputElement的实例。

33

顺便说一下,我不是JavaScript专家,但最近基于Google Maps做了很多事情的时候感觉自己会成为一个。

我实现了一个地图。用户可以搜索Google Places并为其放置标记。文本框就在那里。或者用户可以单击地图将标记放置到他正在寻找的地方,或者拖动标记。

代码保持不变。设计改变了。输入字段的ID和名称也相同。JS代码没有改变。但是这个东西不起作用。

这是网站

Google地图产生了错误。

 InvalidValueError: not an instance of HTMLInputElement
我尝试了这里给出的解决方案,但错误仍然存在。
可能的原因是什么?
以下是代码:
        var map;
        var marker;
        var latLngC;

        function initialize() 
        {
            latLngC = new google.maps.LatLng(14.5800, 121.0000);
            var mapOptions = {
        center: latLngC,
        zoom: 12,
        mapTypeId: google.maps.MapTypeId.ROADMAP,
        };

            map = new google.maps.Map(document.getElementById('source_map'),
        mapOptions);

        var marker = new google.maps.Marker({
                position: latLngC,
                map: map,
                draggable: true
            });

            google.maps.event.addListener(marker, 'dragend', function (x) 
            {
            document.getElementById('src_lat').value = x.latLng.lat();
            document.getElementById('src_long').value = x.latLng.lng();
            document.getElementById('pickup_location').innerHTML = x.latLng.lat()+' , '+x.latLng.lng();
                var geocoder = new google.maps.Geocoder;
                var infowindow = new google.maps.InfoWindow;                
            geocodeLatLng(geocoder, map, infowindow,x.latLng.lat(),x.latLng.lng(),'source_point');
            }); 

            //Get coordinates,address Upon clicking a location in map (Source Map)
            //By Sajeev
            google.maps.event.addListener(map, 'click', function(x) 
            {
            document.getElementById('src_lat').value = x.latLng.lat();
            document.getElementById('src_long').value = x.latLng.lng();
            document.getElementById('pickup_location').innerHTML = x.latLng.lat()+' , '+x.latLng.lng();
                var geocoder = new google.maps.Geocoder;
                var infowindow = new google.maps.InfoWindow;                
            geocodeLatLng(geocoder, map, infowindow,x.latLng.lat(),x.latLng.lng(),'source_point');
            });

        //Add marker upon clicking on map
            //google.maps.event.addDomListener(map, 'click', addMarker);
            google.maps.event.addDomListener(map, 'click', function() { addMarker(map); }); 



        var places1 = new google.maps.places.Autocomplete(document.getElementById('source_point'));
        google.maps.event.addListener(places1, 'place_changed', function () {
            var place1 = places1.getPlace();

            var src_addr = place1.formatted_address;
            var src_lat = place1.geometry.location.lat();
            var src_long = place1.geometry.location.lng();

            var mesg1 = "Address: " + src_addr;
            mesg1 += "\nLatitude: " + src_lat;
            mesg1 += "\nLongitude: " + src_long;
            //alert(mesg1);

                 document.getElementById('src_lat').value = src_lat;
            document.getElementById('src_long').value = src_long;
            document.getElementById('pickup_location').innerHTML = src_lat+' , '+src_long;                 
        });
        //Add marker upon place change
        //google.maps.event.addDomListener(places1, 'place_changed', addMarker);            
            google.maps.event.addDomListener(places1, 'place_changed', function() { addMarker(map); }); 

        }
        google.maps.event.addDomListener(window,'resize',initialize);
        google.maps.event.addDomListener(window, 'load', initialize); 

我的HTML代码看起来像这样:

   <form role="form" id="frm_source" name="frm_source" method="POST" action="index_action.php">

        <div class="form-group">
            <label for="source_point"><h2>Pickup Address</h2></label>
            <textarea type="text" id="source_point" name="source_point"  class="form-control" placeholder="Enter your pick up address here"></textarea>
        </div>

        <div class="form-group">
            <label for="pickup_location"><h3>GPS Cordinates</h3></label>
            <hr>
            <p id="pickup_location"></p>
        </div>

        <div class="form-group">
            <input type="hidden" id="src_lat" name="src_lat" placeholder="latitude" >
            <input type="hidden" id="src_long" name="src_long" placeholder="longitude" >
        </div>

    <input type="submit" name="submit" id="submit" class="btn btn-primary" value="Next to enter destination address" />
    </form>

谷歌地图

<div id="source_map"></div>

展示你的代码...不要只展示错误。 - ScaisEdge
还要添加HTML相关代码...错误似乎与标签ID有关。 - ScaisEdge
我看不到地图div id=source_map的HTML源代码。 - ScaisEdge
添加了地图div @scaisEdge - Sajeev C
12个回答

65

你的领域是 TEXTAREA,从最近的更新开始,谷歌地图自动完成现在仅支持window.HTMLInputElement (INPUT tag)


你知道为什么谷歌停止了吗?有官方链接吗? - Chandru
哦我的天啊。谢谢你啊兄弟。我花了几个小时修改我的代码,这就是解决方案。将<ion-input更改为<input。 - Kyusuf Muhammad
42
我没有文本区域,但是在使用输入标签时仍会出现此错误。 - Jordan

17

这是一个DOM问题。您的JavaScript在加载HTML文档之前就已经加载了。

请确保您的HTML元素先加载,然后再加载JavaScript。

例如:

然后再加载您的JavaScript代码


9
在按照谷歌的教程操作时,我遇到了问题。问题在于你应该在页面加载后执行javascript代码,在调用谷歌地图脚本时可以在GET参数中调用函数。
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places$callback=YourFunctionHere"></script>

YourFunctionHere 是一个回调函数,意味着它只会在页面加载后执行。

或者您可以在页面加载后调用函数。例如:window.onload = Yourfunction();

现在,在该函数内部,您将执行 Google Maps API 相关的操作,如 document.getElementById('source_map') 和所有属于 google 类的方法。


5
我在Angular2中遇到了同样的问题。我的解决方案是将Google Maps的初始化移动到一个函数中,该函数在用户聚焦于自动完成字段时触发。虽然不是最美的解决方案,但它能够正常工作。
代码:
private autocomplete_init: boolean: false;

autocompleteFocus() {
 this.autocomplete_init = true;
 if (!this.autocomplete_init) {
  this._autocomplete = new google.maps.places.Autocomplete(document.getElementById("search_address"), {
  componentRestrictions: {'country': 'dk'}
  }
}

HTML:

<input placeholder="Search" type="text" id="search_address" (focus)="autocompleteFocus()" autofocus>

2
在我的情况下,错误的原因是google.maps.ControlPosition运行了多次。我的谷歌地图显示在模态框中。第一次打开模态框时,一切正常,但下一次,这个错误就会出现。 我的解决方案:只初始化地图一次。
constructor(props) {
        super(props);
        this.state = {
            lat: null,
            lng: null,
            visible: false,
            inited: false
        };
        this.initMap = this.initMap.bind(this);
        this.setModalVisible = this.setModalVisible.bind(this);
    }

    setModalVisible(status) {
        if (!this.state.inited) {
            //Khi chưa init map lần nào (chưa từng mở modal)
            this.setState(
                {
                    visible: true,
                    inited: true
                },
                () => {
                    this.initMap();
                }
            );
        } else {
            // Khi đã init, đóng/mở modal mà k cần init lại
            this.setState({
                visible: status
            });
        }
    }
    initMap() {
        if (this.state.visible) {
            let map = new google.maps.Map(document.getElementById("map"), {
                center: { lat: 21.0277644, lng: 105.8341598 },
                zoom: 10
            });
            const card = document.getElementById("pac-card");
            const input = document.getElementById("pac-input");
            const options = {
                fields: ["formatted_address", "geometry", "name"],
                origin: map.getCenter(),
                strictBounds: false
            };
            map.controls[google.maps.ControlPosition.TOP_CENTER].push(card);
            const autocomplete = new google.maps.places.Autocomplete(
                input,
                options
            );
            autocomplete.bindTo("bounds", map);
            const infowindow = new google.maps.InfoWindow();
            const infowindowContent = document.getElementById(
                "infowindow-content"
            );
            infowindow.setContent(infowindowContent);
            var marker = new google.maps.Marker({
                map
            });
            google.maps.event.addListener(map, "click", e => {
                console.log(e);
                var latLng = e.latLng;
                this.setState({
                    lat: e.latLng.lat(),
                    lng: e.latLng.lng()
                });
                console.log(latLng.lat(), latLng.lng());
                if (marker && marker.setMap) {
                    marker.setMap(null);
                }
                marker = new google.maps.Marker({
                    position: latLng,
                    map: map
                });
            });
            autocomplete.addListener("place_changed", () => {
                infowindow.close();
                const place = autocomplete.getPlace();
                console.log(place);

                if (!place.geometry || !place.geometry.location) {
                    window.alert(
                        "Không tìm thấy vị trí " +
                            place.name +
                            " .Vui lòng chọn trên bản đồ."
                    );
                    return;
                }
                this.setState({
                    lat: place.geometry.location.lat(),
                    lng: place.geometry.location.lng()
                });
                if (marker && marker.setMap) {
                    marker.setMap(null);
                }
                marker = new google.maps.Marker({
                    position: place.geometry.location,
                    map: map
                });
                map.setZoom(16);
                infowindowContent.children["place-name"].textContent =
                    place.name;
                infowindowContent.children["place-address"].textContent =
                    place.formatted_address;
                infowindow.open(map, marker);
            });
        }
    }

你好,我有一个类似的问题(我的自动完成在模态框中只能工作一次)。您可以在代码中指出仅调用一次地图的位置吗? - PhilM

1
我几天前遇到了同样的问题,但是我找到了一个解决方案,如果有人感兴趣 :) 它并不完美,非常棘手,但它可以完成95%的工作!我知道这是一个非常古老的话题,但如果它能帮助到某个人......

思路是添加一个自定义文本区域,并将原始输入文本值绑定到文本区域(使用keyup、keypress、keydown、change事件)。

$('.MyInput').on('keyup keydown keypress change', function() {
  $('myTextarea').val($(this).val());
  emptyPlaceholder($(this), 'Myplaceholder text');
});

function emptyPlaceholder(input, placeholder) {
     // The placeholder of the textarea will hide if the input has a value
     if (input.val().length) {
         $('#triggerInput').attr('placeholder', '');
     } else {
         $('#triggerInput').attr('placeholder', placeholder);
     }
 }

在"隐藏"原始输入的同时,添加一些CSS。它将隐藏您在输入中编写的内容,然后您只会看到文本区域中编写的内容(重要提示:输入的z-index必须高于文本区域的z-index!)。
.MyInput {
   color: transparent;
   background-color: transparent; 
}

这还远非完美,如果有更好的解决方案,我很乐意接受!


1

在按照 Google 教程操作时我遇到了同样的问题。我的情况是 async 关键字导致谷歌地图脚本异步执行,而页面的其余部分继续解析。以下是解决办法:

  1. 将谷歌地图脚本放置在相关 HTML 元素之后(如 Prashant 所指出的)
  2. 使用 defer 关键字而不是 async 关键字调用谷歌地图脚本。代码如下:
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places$callback=YourFunctionHere" defer></script>

使用defer可以确保脚本在页面解析完成后执行(source)。

1

对于Angular

我在ngOnInit()中初始化了autocomplete,因此出现了错误。 我只需将初始化移动到ngAfterViewInit()中,一切都可以正常工作。

代码:

  ngAfterViewInit(): void {
    this.autocomplete = new google.maps.places.Autocomplete(
      (this._document.getElementById('input')),
      { types: ['geocode'] }
    );
  }

0
.pac-container { z-index: 1051 !important; }


CSS 中的代码,用于设置页面中自动完成下拉框的优先级。

0

InvalidValueError 在尝试在 iframe 中配置 Google Places Autocomplete 时也会发生。如果您从父 DOM 进行操作,您将会遇到此错误,因为:

如果您的应用程序是那些使用跨窗口 DOM 检查(或类似功能)的罕见应用程序之一,则 window.HTMLInputElement === otherWindow.HTMLInputElement 将为 false,因此 instanceof 运算符也可能意外返回 false。这同样适用于 iframe 和弹出窗口。在这些情况下,检查 tagName 可以起作用,正如其他答案已经提到的那样。- John Weisz

解决方案有两个:

  1. 将 Google 脚本注入到 iframe 中。
  2. 使用 iframe.contentWindow 获取 iframe 的 window 对象,并从中调用 google.maps.places.Autocomplete()

以下是一个示例:

var GOOGLE_API_KEY = 'fill-me';
var AUTOCOMPLETE_CONFIG = { /* fill-me */  };
function handlePlaceSelect() { /* fill-me */  }

var iframeWindow = iframe.contentWindow;
var iframeDocument = iframe.contentDocument;

var googleScript = document.createElement("script");
googleScript.type = "text/javascript";
googleScript.src = "https://maps.googleapis.com/maps/api/js?key=" + GOOGLE_API_KEY + "&libraries=places";
iframeDocument.body.appendChild(googleScript);

googleScript.addEventListener('load', function() {
  autoComplete = new iframeWindow.google.maps.places.Autocomplete(addressInput, AUTOCOMPLETE_CONFIG);
  autoComplete.addListener("place_changed", function () {
    handlePlaceSelect();
  });
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接