To handle the Google Places Autocomplete with Livewire, you need to ensure that the Livewire component is aware of the changes made by the Google Places Autocomplete script. The issue you're facing is likely due to the timing of the events and how they are dispatched.
Here's a refined approach to ensure that the Livewire component detects the changes correctly:
-
Debounce the input events: This will help in ensuring that the events are not fired too quickly, which might be causing the autocomplete dropdown to get stuck.
-
Use a custom event: Instead of directly dispatching the 'input' event, you can create a custom event that Livewire can listen to.
Here's the updated script:
let autocomplete;
let address1Field;
let address2Field;
let postalField;
let serviceCity;
let serviceState;
let serviceCounty;
let serviceCountry;
function initAutocomplete() {
address1Field = document.querySelector("#service_address");
address2Field = document.querySelector("#service_suite");
postalField = document.querySelector("#service_zip");
serviceCity = document.querySelector("#service_city");
serviceState = document.querySelector("#service_state");
serviceCounty = document.querySelector("#service_county");
serviceCountry = document.querySelector("#service_country");
autocomplete = new google.maps.places.Autocomplete(address1Field, {
componentRestrictions: { country: ["us", "ca"] },
fields: ["address_components", "geometry"],
types: ["address"],
});
address1Field.focus();
autocomplete.addListener("place_changed", fillInAddress);
}
function fillInAddress() {
const place = autocomplete.getPlace();
let address1 = "";
let postcode = "";
for (const component of place.address_components) {
const componentType = component.types[0];
switch (componentType) {
case "street_number": {
address1 = `${component.long_name} ${address1}`;
break;
}
case "route": {
address1 += component.short_name;
break;
}
case "postal_code": {
postcode = `${component.long_name}${postcode}`;
break;
}
case "postal_code_suffix": {
postcode = `${postcode}-${component.long_name}`;
break;
}
case "locality":
serviceCity.value = component.long_name;
break;
case "administrative_area_level_1": {
serviceState.value = component.short_name;
break;
}
case "administrative_area_level_2":
serviceCounty.value = component.long_name;
break;
case "country":
serviceCountry.value = component.long_name;
break;
}
}
address1Field.value = address1;
postalField.value = postcode;
// Dispatch custom event to notify Livewire
dispatchLivewireEvent();
}
function dispatchLivewireEvent() {
const event = new CustomEvent('google-autocomplete', {
detail: {
address1: address1Field.value,
address2: address2Field.value,
city: serviceCity.value,
state: serviceState.value,
postal: postalField.value,
county: serviceCounty.value,
country: serviceCountry.value,
}
});
document.dispatchEvent(event);
}
window.initAutocomplete = initAutocomplete;
In your Livewire component, you can listen for this custom event and update the properties accordingly:
<script>
document.addEventListener('google-autocomplete', function (event) {
@this.set('address1', event.detail.address1);
@this.set('address2', event.detail.address2);
@this.set('city', event.detail.city);
@this.set('state', event.detail.state);
@this.set('postal', event.detail.postal);
@this.set('county', event.detail.county);
@this.set('country', event.detail.country);
});
</script>
This approach ensures that the Livewire component is updated with the values from the Google Places Autocomplete script without causing the autocomplete dropdown to get stuck.