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
相关产品推荐
相关产品推荐

