Skip to content

Instantly share code, notes, and snippets.

@TWithers
Last active April 25, 2024 07:34
Show Gist options
  • Save TWithers/a6e385b14ce12b2880d811fe098fcd4a to your computer and use it in GitHub Desktop.
Save TWithers/a6e385b14ce12b2880d811fe098fcd4a to your computer and use it in GitHub Desktop.
AlpineJS implementation of Google Places Autocomplete
<div x-data="googlePlacesAutocomplete" class="grid grid-cols-3 gap-2">
<input type="text" x-model="address.address1" x-ref="googleAutocomplete" autocomplete="chrome-off" class="col-span-3 sm:col-span-2 order-1" placeholder="Add&#8204;ress">
<input type="text" x-model="address.address2" placeholder="Apt/Ste" class="col-span-3 sm:col-span-1 order-2">
<input type="text" x-model="address.city" placeholder="Ci&#8204;ty" class="col-span-1" x-bind:class="`order-${order.locality}`">
<select x-model="address.state" placeholder="St‌ate" class="col-span-1 order-4" x-show="isUSA">
<option value="">State</option>
<option value="AL">Alabama</option>
<option value="AK">Alaska</option>
<option value="AZ">Arizona</option>
<option value="AR">Arkansas</option>
<option value="CA">California</option>
<option value="CO">Colorado</option>
<option value="CT">Connecticut</option>
<option value="DE">Delaware</option>
<option value="DC">District Of Columbia</option>
<option value="FL">Florida</option>
<option value="GA">Georgia</option>
<option value="HI">Hawaii</option>
<option value="ID">Idaho</option>
<option value="IL">Illinois</option>
<option value="IN">Indiana</option>
<option value="IA">Iowa</option>
<option value="KS">Kansas</option>
<option value="KY">Kentucky</option>
<option value="LA">Louisiana</option>
<option value="ME">Maine</option>
<option value="MD">Maryland</option>
<option value="MA">Massachusetts</option>
<option value="MI">Michigan</option>
<option value="MN">Minnesota</option>
<option value="MS">Mississippi</option>
<option value="MO">Missouri</option>
<option value="MT">Montana</option>
<option value="NE">Nebraska</option>
<option value="NV">Nevada</option>
<option value="NH">New Hampshire</option>
<option value="NJ">New Jersey</option>
<option value="NM">New Mexico</option>
<option value="NY">New York</option>
<option value="NC">North Carolina</option>
<option value="ND">North Dakota</option>
<option value="OH">Ohio</option>
<option value="OK">Oklahoma</option>
<option value="OR">Oregon</option>
<option value="PA">Pennsylvania</option>
<option value="RI">Rhode Island</option>
<option value="SC">South Carolina</option>
<option value="SD">South Dakota</option>
<option value="TN">Tennessee</option>
<option value="TX">Texas</option>
<option value="UT">Utah</option>
<option value="VT">Vermont</option>
<option value="VA">Virginia</option>
<option value="WA">Washington</option>
<option value="WV">West Virginia</option>
<option value="WI">Wisconsin</option>
<option value="WY">Wyoming</option>
</select>
<input type="text" x-model="address.state" placeholder="Sta&#8204;te" class="col-span-1" x-show="!isUSA && hasState" x-bind:class="`order-${order.region}`">
<input type="text" x-model="address.zip" placeholder="Z&#8204;ip" class="col-span-1" x-bind:class="`order-${order['postal-code']}`">
<input type="text" x-model="address.country" placeholder="Coun&#8204;try" class="col-span-3 order-6" x-bind:class="{'col-span-1': !hasState, 'col-span-3': hasState}" x-show="!isUSA">
<input type="hidden" x-model="externalModel" x-modelable="address" class="order-3 order-5">
</div>
<script async src="https://maps.googleapis.com/maps/api/js?key=YOUR_KEY_HERE&libraries=places&callback=googleReady"></script>
<script>
function googleReady() {
document.dispatchEvent(new Event('google:init'));
}
document.addEventListener('alpine:init', () => {
Alpine.data('googlePlacesAutocomplete', () => ({
address: {
address1: '',
address2: '',
city: '',
state: '',
zip: '',
country: '',
},
order: {
'locality': 3,
'region': 4,
'postal-code': 5,
},
isUSA: true,
hasState: true,
fullResultData: {},
element: null,
autocomplete: null,
init() {
this.element = this.$el.querySelector(':scope [x-ref="googleAutocomplete"]');
if (this.element === null) {
console.error("Cannot find Google Places Autocomplete input [x-ref=\"googleAutocomplete\"]");
return;
}
if (typeof window.google === 'undefined') {
document.addEventListener('google:init', () => {
this.initAutocomplete();
});
} else {
this.initAutocomplete();
}
},
resetData() {
this.address = {
address2: '',
city: '',
state: '',
zip: '',
country: '',
};
},
initAutocomplete() {
this.autocomplete = new window.google.maps.places.Autocomplete(this.element, {
types: ['address']
});
window.google.maps.event.addListener(this.autocomplete, 'place_changed', ()=>this.handleResponse(this.autocomplete.getPlace()));
},
handleResponse(placeResultData) {
this.fullResultData = placeResultData;
this.resetData();
const addressFragment = document.createRange().createContextualFragment(placeResultData.adr_address);
this.address.address1 = addressFragment.querySelector(".street-address") ? addressFragment.querySelector(".street-address").innerHTML : '';
this.address.address2 = addressFragment.querySelector(".extended-address") ? addressFragment.querySelector(".extended-address").innerHTML : '';
this.address.city = addressFragment.querySelector(".locality") ? addressFragment.querySelector(".locality").innerHTML : '';
this.address.state = addressFragment.querySelector(".region") ? addressFragment.querySelector(".region").innerHTML : '';
this.address.zip = addressFragment.querySelector(".postal-code") ? addressFragment.querySelector(".postal-code").innerHTML : '';
this.address.country = addressFragment.querySelector(".country-name") ? addressFragment.querySelector(".country-name").innerHTML : '';
this.isUSA = ['united states', 'usa', 'us', 'united states of america'].indexOf(this.address.country.toLowerCase()) !== -1;
this.hasState = this.address.state !== '';
this.$dispatch('place-chosen', {address: this.address, resultResponse: this.fullResultData});
}
}))
})
</script>
@TWithers
Copy link
Author

Modified to support an external x-model that is populated with the address.
Simplified lookup using the adr_address and creating a contextual fragment to query against.
Started supporting ordering of inputs when another country is chosen and the address format is different (address, city, postal, country for example)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment