Google Map标记点击触发$wire未定义错误及表单验证问题求助
问题:Google Map添加Marker时的Livewire $wire未定义错误及必填字段问题
错误信息
VM951 livewire.js:13 Uncaught TypeError: Cannot read properties of undefined (reading '$wire') at Livewire.value (VM951 livewire.js:13:145634) at placeMarkerAndPanTo (make:2811:27) at make:2792:11 at geocoder.js:6:1385 at geocoder.js:3:420 at bza (geocoder.js:2:218) at gia.e [as m] (geocoder.js:3:339) at Object.c [as _yj5gms] (common.js:123:253) at GeocodeService.Search?5m2&1d24.745676471010597&2d46.7278229712639&9sen-US&callback=_xdc_._yj5gms&key=AIzaSyDy4tKkS30XU9DJsUA5cqLzg-jtynKS18s&token=45746:1:28
问题现象
- 点击地图选择地点时触发上述错误
- 点击保存按钮时提示字段必填,但已在地图上选择了地点
相关代码
页面脚本部分(@section('scripts'))
@section('scripts') <script src="https://maps.googleapis.com/maps/api/js?key={{env("GOOGLE_KEY")}}&libraries=places&v=weekly"> </script> <script src="{{ asset('dashboard/assets/js/pages/crud/forms/widgets/select2.js') }}"></script> <script> $(document).ready(function() { $('#kt_select2_3').select2({ placeholder: '', }).on('change', function() { @this.properties = $(this).val(); }); }); function mapLocation() { var directionsDisplay; var directionsService = new google.maps.DirectionsService(); var map; var lat, lng; var markers = []; var gmarkers = []; function initialize() { directionsDisplay = new google.maps.DirectionsRenderer(); var riyad = new google.maps.LatLng(24.729518, 46.723341); var mapOptions = { zoom: 13, center: riyad, mapTypeId: google.maps.MapTypeId.ROADMAP }; map = new google.maps.Map(document.getElementById('map'), mapOptions); map.addListener('click', function(e) { var geocoder = new google.maps.Geocoder(); geocoder.geocode({ 'latLng': e.latLng }, function(results, status) { if (status == google.maps.GeocoderStatus.OK) { if (results[1]) { // 注释的代码 } } placeMarkerAndPanTo(e.latLng, map, results[1].formatted_address); }); }); var marker = new google.maps.Marker({ position: markers, map: map }); function placeMarkerAndPanTo(latLng, map, results) { if (document.getElementById("pickup_lat").value.length == 0) { document.getElementById("pickup_lat").value = latLng.lat(); document.getElementById("pickup_lng").value = latLng.lng(); document.getElementById("address_pickUp").value = results; marker.setPosition(latLng); map.panTo(latLng); @this.pickup_lat = latLng.lat(); @this.pickup_lng = latLng.lng(); } else { document.getElementById("dropoff_lat").value = latLng.lat(); document.getElementById("dropoff_lng").value = latLng.lng(); document.getElementById("address_dropOff").value = results; marker.setPosition(latLng); map.panTo(latLng); @this.dropoff_lat = latLng.lat(); @this.dropoff_lng = latLng.lng(); } } directionsDisplay.setMap(map); google.maps.event.addDomListener(document.getElementById('routebtn'), 'click', calcRoute); // 搜索框相关代码 var input = document.getElementById('pac-input'); var searchBox = new google.maps.places.SearchBox(input); map.controls[google.maps.ControlPosition.TOP_LEFT].push(input); map.addListener('bounds_changed', function() { searchBox.setBounds(map.getBounds()); }); var markers = []; searchBox.addListener('places_changed', function() { var places = searchBox.getPlaces(); if (places.length == 0) { return; } markers.forEach(function(marker) { marker.setMap(null); }); markers = []; var bounds = new google.maps.LatLngBounds(); places.forEach(function(place) { var icon = { url: place.icon, size: new google.maps.Size(71, 71), origin: new google.maps.Point(0, 0), anchor: new google.maps.Point(17, 34), scaledSize: new google.maps.Size(25, 25) }; console.log("latitude: " + place.geometry.location.lat() + ", longitude: " + place.geometry.location.lng()); markers.push(new google.maps.Marker({ map: map, icon: icon, title: place.name, position: place.geometry.location })); if (place.geometry.viewport) { bounds.union(place.geometry.viewport); } else { bounds.extend(place.geometry.location); } }); map.fitBounds(bounds); }); } </script> @endsection
make-trip.blade.php相关代码
<div class="col-lg-12" wire:ignore> <div class="col-lg-3"> <x-input type="text" field="map" style="margin: 10px; z-index: 0; position: absolute; cursor: pointer; left: 0px; top: 0px;width:350px" placeholder="Search Box" id="pac-input"></x-input> </div> </div>
解决方案
1. 修复Livewire上下文丢失问题
错误核心是@this在Geocoder异步回调中无法正确获取Livewire组件实例,替换为直接获取组件实例的方式:
修改placeMarkerAndPanTo函数中的Livewire赋值代码:
// 替换原来的@this赋值 const component = window.Livewire.find('{{ $this->id }}'); // 取件地址赋值 component.set('pickup_lat', latLng.lat()); component.set('pickup_lng', latLng.lng()); // 收件地址赋值(else分支) component.set('dropoff_lat', latLng.lat()); component.set('dropoff_lng', latLng.lng());
2. 处理Geocoder结果为空的情况
当前代码直接使用results[1].formatted_address,若结果长度不足2会导致undefined,修改Geocoder回调逻辑:
map.addListener('click', function(e) { var geocoder = new google.maps.Geocoder(); geocoder.geocode({ 'latLng': e.latLng }, function(results, status) { let address = ''; if (status === google.maps.GeocoderStatus.OK && results.length > 0) { // 优先使用第一个结果,通常是最精确匹配 address = results[0].formatted_address; } placeMarkerAndPanTo(e.latLng, map, address); }); });
3. 绑定输入框与Livewire字段
为隐藏输入框添加wire:model,让输入框值变化时自动同步到组件,避免手动赋值的上下文问题:
<!-- 取件地址相关输入框 --> <input type="hidden" id="pickup_lat" wire:model="pickup_lat"> <input type="hidden" id="pickup_lng" wire:model="pickup_lng"> <input type="text" id="address_pickUp" wire:model="address_pickUp"> <!-- 收件地址相关输入框 --> <input type="hidden" id="dropoff_lat" wire:model="dropoff_lat"> <input type="hidden" id="dropoff_lng" wire:model="dropoff_lng"> <input type="text" id="address_dropOff" wire:model="address_dropOff">
4. 修正Marker初始化问题
当前Marker初始化时position: markers(空数组)会导致Marker无法正常显示,修改为:
var marker = null; // 在placeMarkerAndPanTo中创建或更新Marker function placeMarkerAndPanTo(latLng, map, results) { if (!marker) { marker = new google.maps.Marker({ position: latLng, map: map }); } else { marker.setPosition(latLng); } // 其他赋值逻辑... }
内容的提问来源于stack exchange,提问作者Mustafa Ahmed
相关产品推荐
相关产品推荐

