I'm making this form where the user types in their postcode and it autocompletes the full address from google.maps.places dropdown list. The only thing that's missing is the latitude and longitude which I intend to make hidden fields for and then onsubmit post to my google sheets spreadsheet in the appropriate fields.
What I'm stuck on, is combining the Geocoding API call, with the Autocomplete Javascript function. What I'm trying to do, is add in a Geocoding API call with the autocomplete function so that the Lat. and Lng is sent to the hidden fields, I've been trying to figure this out for 3 days, I wonder if anyone has a solution.
Here is the code I have:
var placeSearch, autocomplete;
var componentForm = {
street_number: 'short_name',
route: 'long_name',
locality: 'long_name',
administrative_area_level_1: 'short_name',
country: 'long_name',
postal_code: 'short_name'
};
function initAutocomplete() {
// Create the autocomplete object, restricting the search to geographical
// location types.
autocomplete = new google.maps.places.Autocomplete(
/** @type {!HTMLInputElement} */(document.getElementById('autocomplete')),
{types: ['geocode']});
// When the user selects an address from the dropdown, populate the address
// fields in the form.
autocomplete.addListener('place_changed', fillInAddress);
}
function fillInAddress() {
// Get the place details from the autocomplete object.
var place = autocomplete.getPlace();
for (var component in componentForm) {
document.getElementById(component).value = '';
document.getElementById(component).disabled = false;
}
// Get each component of the address from the place details
// and fill the corresponding field on the form.
for (var i = 0; i < place.address_components.length; i ) {
var addressType = place.address_components[i].types[0];
if (componentForm[addressType]) {
var val = place.address_components[i][componentForm[addressType]];
document.getElementById(addressType).value = val;
}
}
}
// Bias the autocomplete object to the user's geographical location,
// as supplied by the browser's 'navigator.geolocation' object.
function geolocate() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
var geolocation = {
lat: position.coords.latitude,
lng: position.coords.longitude
};
var circle = new google.maps.Circle({
center: geolocation,
radius: position.coords.accuracy
});
autocomplete.setBounds(circle.getBounds());
});
}
}
<form id="myform" method="POST"
action="https://script.google.com/macros/s/AKfycbzF_r-4ENEXSMD36Ry_gQ9iSQ5dqfpZiw3VytR7LmpSAwxbEcRelxhGJroi8QCBavEI/exec"
autocomplete="off" role="form">
<input autocomplete="false" name="hidden" type="text" style="display:none;">
<div >
<label>Business address</label>
<div >
<input id="autocomplete" autocomplete="off" autofill="off" placeholder="Postcode" onFocus="geolocate()" type="text"
>
</div>
</div>
<br>
<div >
<label>Number</label>
<div >
<input name="No." id="street_number" disabled="false" required>
</div>
<label>Street</label>
<div >
<input name="Street" id="route" disabled="true" required>
</div>
</div>
<br>
<div >
<label>City</label>
<div >
<input name="City" id="locality" disabled="true" required>
</div>
<label>State</label>
<div >
<input name="State" id="administrative_area_level_1" disabled="true">
</div>
</div>
<br>
<div >
<label>Postal/zipcode</label>
<div >
<input name="Postcode" id="postal_code" disabled="true" required>
</div>
<label>Country</label>
<div >
<input name="Country" id="country" disabled="true">
</div>
</div>
<div >
<label>Lat</label>
<div >
<input name="Lat" id="Lat" disabled="true" required>
</div>
<label>Lng</label>
<div >
<input name="Lng" id="Lng" disabled="true">
</div>
</div>
</div>
<div >
<div id="submit">
<button type="submit" value="Submit" >Submit</button>
</div>
</div>
</form>
<script
src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB_MrpX85obMpsk_eEdfE-iPIt06qbHyt0&libraries=places&callback=initAutocomplete"
async defer></script>
Now I also have this code snippet for calling the google geocoding API
document.getElementById('myform').addEventListener('submit', function(e){
e.preventDefault(); //prevent form submit
const place = autocomplete.getPlace(); //get place from autocomplete
if (!place || !place.geometry) { //check if valid location
swal("You have provided an Invalid address","Enter a valid Address", "warning");
return;
}
// It is valid, proceed to geocode!
else {
// Listen for form submit
document.getElementById('myForm').addEventListener('submit', geocode);
function geocode(e){
// Prevent actual submit
e.preventDefault();
var location = document.getElementById('location-input').value; //* I think this is where I might have made a mistake
axios.get('https://maps.googleapis.com/maps/api/geocode/json', {
params:{
address: location,
key: 'AIzaSyB_MrpX85obMpsk_eEdfE-iPIt06qbHyt0'
}
})
.then(function(response){
// Log full response
console.log(response);
// Formatted Address
var formattedAddress = response.data.results[0].formatted_address;
// Address Components
var addressComponents = response.data.results[0].address_components;
// Get values from the input fields
var veg_planted = getInputVal('veg_planted');
// Get geometry
var lat = response.data.results[0].geometry.location.lat;
var lng = response.data.results[0].geometry.location.lng;
var coords= (formattedAddress ": " lat "," lng);
console.log(coords);
// Save messages
saveMessage(veg_planted, coords);
})
.catch(function(error){
console.log(error);
});
}
}
});
Can this function be integrated with the autocomplete function I have to make the form fill out Lat. and Lng. values? If anyone out there has the solution it would help me a lot. Thank you.
CodePudding user response:
You don't need to use the geocoder. The places API returns the lat/lng coordinates in its response (if it has them).
PlaceResult.geometry
geometry optional
Type: PlaceGeometry optional
The Place’s geometry-related information.
PlaceGeometry interface
Defines information about the geometry of a Place.
Properties
location optional
Type: LatLng optional
The Place’s position.
document.getElementById("Lat").value = place.geometry.location.lat();
document.getElementById("Lng").value = place.geometry.location.lng();
working code snippet:
var placeSearch, autocomplete;
var componentForm = {
street_number: 'short_name',
route: 'long_name',
locality: 'long_name',
administrative_area_level_1: 'short_name',
country: 'long_name',
postal_code: 'short_name'
};
function initAutocomplete() {
// Create the autocomplete object, restricting the search to geographical
// location types.
autocomplete = new google.maps.places.Autocomplete(
/** @type {!HTMLInputElement} */
(document.getElementById('autocomplete')), {
types: ['geocode']
});
// When the user selects an address from the dropdown, populate the address
// fields in the form.
autocomplete.addListener('place_changed', fillInAddress);
}
function fillInAddress() {
// Get the place details from the autocomplete object.
var place = autocomplete.getPlace();
for (var component in componentForm) {
document.getElementById(component).value = '';
document.getElementById(component).disabled = false;
}
document.getElementById("Lat").value = place.geometry.location.lat();
document.getElementById("Lng").value = place.geometry.location.lng();
// Get each component of the address from the place details
// and fill the corresponding field on the form.
for (var i = 0; i < place.address_components.length; i ) {
var addressType = place.address_components[i].types[0];
if (componentForm[addressType]) {
var val = place.address_components[i][componentForm[addressType]];
document.getElementById(addressType).value = val;
}
}
}
// Bias the autocomplete object to the user's geographical location,
// as supplied by the browser's 'navigator.geolocation' object.
function geolocate() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
var geolocation = {
lat: position.coords.latitude,
lng: position.coords.longitude
};
var circle = new google.maps.Circle({
center: geolocation,
radius: position.coords.accuracy
});
autocomplete.setBounds(circle.getBounds());
});
}
}
<form id="myform" method="POST" action="https://script.google.com/macros/s/AKfycbzF_r-4ENEXSMD36Ry_gQ9iSQ5dqfpZiw3VytR7LmpSAwxbEcRelxhGJroi8QCBavEI/exec" autocomplete="off" role="form">
<input autocomplete="false" name="hidden" type="text" style="display:none;">
<div >
<label>Business address</label>
<div >
<input id="autocomplete" autocomplete="off" autofill="off" placeholder="Postcode" onFocus="geolocate()" type="text" >
</div>
</div>
<br>
<div >
<label>Number</label>
<div >
<input name="No." id="street_number" disabled="false" required>
</div>
<label>Street</label>
<div >
<input name="Street" id="route" disabled="true" required>
</div>
</div>
<br>
<div >
<label>City</label>
<div >
<input name="City" id="locality" disabled="true" required>
</div>
<label>State</label>
<div >
<input name="State" id="administrative_area_level_1" disabled="true">
</div>
</div>
<br>
<div >
<label>Postal/zipcode</label>
<div >
<input name="Postcode" id="postal_code" disabled="true" required>
</div>
<label>Country</label>
<div >
<input name="Country" id="country" disabled="true">
</div>
</div>
<div >
<label>Lat</label>
<div >
<input name="Lat" id="Lat" disabled="true" required>
</div>
<label>Lng</label>
<div >
<input name="Lng" id="Lng" disabled="true">
</div>
</div>
</div>
<div >
<div id="submit">
<button type="submit" value="Submit">Submit</button>
</div>
</div>
</form>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB_MrpX85obMpsk_eEdfE-iPIt06qbHyt0&libraries=places&callback=initAutocomplete" async defer></script>