You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 21:30:47