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

Bootstrap 5模态框中Google Places新版Autocomplete事件未触发

问题:Bootstrap 5模态框中Google Places Autocomplete的gmp-placeselect事件不触发

问题描述

尝试在Bootstrap 5模态框中使用Google Places新版Autocomplete组件获取地址,组件能正常渲染到模态框内,但点击下拉选项时gmp-placeselect事件完全不触发。将相同组件放在页面主体中时,事件可正常执行,控制台无任何报错。

已完成的测试:

  • 将组件移至页面主体:事件成功触发
  • 替换Bootstrap模态框为原生<dialog>:问题依旧存在

说明组件在模态框环境下存在异常。

解决方案

问题根源在于模态框初始处于隐藏状态,Autocomplete组件初始化时无法正确绑定事件;另外Autocomplete的下拉选项挂载在<body>上,点击事件可能被模态框的事件处理拦截。解决方法是延迟初始化模态框内的Autocomplete组件,直到模态框完全显示后再创建实例。

修改后的代码

JavaScript部分

async function initAutocomplete() {
  const { PlaceAutocompleteElement } = await google.maps.importLibrary("places");

  // 页面主体的Autocomplete(保持原逻辑)
  const placeAutocomplete2 = new PlaceAutocompleteElement();
  document.getElementById("google-autocomplete-page").appendChild(placeAutocomplete2);
  placeAutocomplete2.addEventListener("gmp-placeselect", async ({ place }) => {
    await place.fetchFields({ fields: ["addressComponents"] });
    console.log(place.toJSON());
  });

  // 监听模态框显示事件,延迟初始化内部的Autocomplete
  const addressModal = document.getElementById("addressModal");
  addressModal.addEventListener("shown.bs.modal", async () => {
    // 避免重复初始化
    if (document.querySelector("#google-address-autocomplete gmp-place-autocomplete")) return;
    
    const placeAutocomplete = new PlaceAutocompleteElement();
    document.getElementById("google-address-autocomplete").appendChild(placeAutocomplete);
    placeAutocomplete.addEventListener("gmp-placeselect", async ({ place }) => {
      await place.fetchFields({ fields: ["addressComponents"] });
      const data = place.toJSON();
      console.log(data);
      // 自动填充模态框表单
      document.getElementById("address1").value = data.addressComponents?.find(c => c.types.includes("street_number"))?.long_name + " " + data.addressComponents?.find(c => c.types.includes("route"))?.long_name || "";
      document.getElementById("city").value = data.addressComponents?.find(c => c.types.includes("locality"))?.long_name || "";
      document.getElementById("postcode").value = data.addressComponents?.find(c => c.types.includes("postal_code"))?.long_name || "";
    });
  });
}

initAutocomplete();

HTML部分(无需修改)

<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">

<div id="body" class="container-fluid ps-0 pe-0">
  <div class="container-fluid booking">
    <div class="row mt-3 booking__inputs">
      <customer-details class="col-12">
        <div class="row align-items-end">
          <h4>Modal</h4>
          <div class="col-12 col-md-auto">
            <label for="group_id" class="form-label">Address</label>
            <div class="input-group">
              <input type="text" class="form-control" id="current_address" readonly>
              <button type="button" class="btn btn-outline-primary" data-bs-toggle="modal" data-bs-target="#addressModal" id="edit-address">Address</button>
            </div>
          </div>
        </div>
        <div class="row mt-3">
          <h4>Page based</h4>
          <div class="col-12 col-md-auto">
            <label class="form-label">Lookup address</label>
            <div id="google-autocomplete-page"></div>
          </div>
        </div>
      </customer-details>
    </div>
  </div>

  <div class="modal fade" data-bs-keyboard="false" id="addressModal" tabindex="-1" aria-labelledby="address detail" aria-hidden="true" style="display: none;">
    <div class="modal-dialog">
      <div class="modal-content">
        <div class="modal-header">
          <h1 class="modal-title fs-5">Address</h1>
          <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
        </div>
        <div class="modal-body">
          <div class="container-fluid">
            <div class="row">
              <div class="col-12 mt-2">
                <label class="form-label">Search for address:</label>
                <div id="google-address-autocomplete"></div>
              </div>
              <div class="col-12 mt-2">
                <label for="address1" class="form-label">Address 1</label>
                <input type="text" class="form-control" name="address1" id="address1" value="">
              </div>
              <div class="col-12 mt-2">
                <label for="address2" class="form-label">Address 2</label>
                <input type="text" class="form-control" name="address2" id="address2" value="">
              </div>
              <div class="col-12 mt-2">
                <label for="city" class="form-label">City</label>
                <input type="text" class="form-control" name="city" id="city" value="" required="">
              </div>
              <div class="col-12 mt-2">
                <label for="postcode" class="form-label">Postcode</label>
                <input type="text" class="form-control" name="postcode" id="postcode" value="" required="">
              </div>
            </div>
          </div>
        </div>
        <div class="modal-footer">
          <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
          <button type="button" class="btn btn-primary" id="save-address" data-bs-dismiss="modal">Save changes</button>
        </div>
      </div>
    </div>
  </div>
</div>
<script>
  (g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))})({
    key: "AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk",
    v: "beta",
  });
</script>  
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.8/dist/umd/popper.min.js" integrity="sha384-I7E8VVD/ismYTF4hNIPjVp/Zjvgyol6VFvRkX/vR+Vc4jQkC+hVqc2pM8ODewa9r" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.min.js" integrity="sha384-0pUGZvbkm6XF6gxjEnlmuGrJXVbNuzT9qBBavbLwCsOGabYfZo0T0to5eqruptLy" crossorigin="anonymous"></script>

关键说明

  • 利用Bootstrap模态框的shown.bs.modal事件,确保在模态框完全显示后再初始化Autocomplete组件,此时组件能正确绑定事件
  • 添加重复初始化判断,避免每次打开模态框都创建新的组件实例
  • 新增地址数据自动填充到模态框表单的逻辑,提升使用便利性

内容的提问来源于stack exchange,提问作者Gary Thompson

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 18:24:53