Last active
April 25, 2024 07:34
-
-
Save TWithers/a6e385b14ce12b2880d811fe098fcd4a to your computer and use it in GitHub Desktop.
AlpineJS implementation of Google Places Autocomplete
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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‌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‌ty" class="col-span-1" x-bind:class="`order-${order.locality}`"> | |
<select x-model="address.state" placeholder="State" 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‌te" class="col-span-1" x-show="!isUSA && hasState" x-bind:class="`order-${order.region}`"> | |
<input type="text" x-model="address.zip" placeholder="Z‌ip" class="col-span-1" x-bind:class="`order-${order['postal-code']}`"> | |
<input type="text" x-model="address.country" placeholder="Coun‌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> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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)