javascripthtmlgoogle-mapsstreet-address

Autocomplete address with google api


I have programmed a simple page where the user can input their address into a search area. Based on the input the address is autocompleted via Google Maps API. Once the user selects one of the addresses then the fields are filled. Everything works, except for the Province/State. The dropdown is populated with the correct provinces/states based on the country dropdown. However, it fails to selected the correct province/state based on the autocomplete selection. What Am I doing wrong here?

<!DOCTYPE html>
<html>

<head>
    <title>Google Places API Autocomplete</title>
    <script
        src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&libraries=places"></script>
    <script>
        function initialize() {
            var senderStreetInput = document.getElementById('sender_street');
            var senderApartmentInput = document.getElementById('sender_apartment');
            var senderCityInput = document.getElementById('sender_city');
            var senderStateSelect = document.getElementById('sender_state');
            var senderPostalCodeInput = document.getElementById('sender_postal_code');
            var senderCountrySelect = document.getElementById('sender_country');
            var senderStreetAutocomplete = new google.maps.places.Autocomplete(senderStreetInput, {
                types: ['address']
            });
            var senderApartmentAutocomplete = new google.maps.places.Autocomplete(senderApartmentInput, {
                types: ['address']
            });
            var senderCityAutocomplete = new google.maps.places.Autocomplete(senderCityInput, {
                types: ['(cities)']
            });
            senderCountrySelect.addEventListener('change', function () {
                var country = this.value;
                senderStateSelect.innerHTML = '';
                if (country === 'Canada') {
                    var provinces = [
                        'Alberta', 'British Columbia', 'Manitoba', 'New Brunswick', 'Newfoundland and Labrador',
                        'Northwest Territories', 'Nova Scotia', 'Nunavut', 'Ontario', 'Prince Edward Island',
                        'Quebec', 'Saskatchewan', 'Yukon'
                    ];
                } else if (country === 'United States') {
                    var states = [
                        'Alabama', 'Alaska', 'Arizona', 'Arkansas', 'California', 'Colorado', 'Connecticut',
                        'Delaware', 'Florida', 'Georgia', 'Hawaii', 'Idaho', 'Illinois', 'Indiana', 'Iowa',
                        'Kansas', 'Kentucky', 'Louisiana', 'Maine', 'Maryland', 'Massachusetts', 'Michigan',
                        'Minnesota', 'Mississippi', 'Missouri', 'Montana', 'Nebraska', 'Nevada', 'New Hampshire',
                        'New Jersey', 'New Mexico', 'New York', 'North Carolina', 'North Dakota', 'Ohio',
                        'Oklahoma', 'Oregon', 'Pennsylvania', 'Rhode Island', 'South Carolina', 'South Dakota',
                        'Tennessee', 'Texas', 'Utah', 'Vermont', 'Virginia', 'Washington', 'West Virginia',
                        'Wisconsin', 'Wyoming'
                    ];
                }
                var option = document.createElement('option');
                option.value = '';
                option.textContent = 'Select a state/province';
                senderStateSelect.appendChild(option);
                if (provinces) {
                    provinces.forEach(function (province) {
                        var option = document.createElement('option');
                        option.value = province;
                        option.textContent = province;
                        senderStateSelect.appendChild(option);
                    });
                } else if (states) {
                    states.forEach(function (state) {
                        var option = document.createElement('option');
                        option.value = state;
                        option.textContent = state;
                        senderStateSelect.appendChild(option);
                    });
                }
                senderStateSelect.disabled = false;
            });
            senderStreetAutocomplete.addListener('place_changed', function () {
                var place = senderStreetAutocomplete.getPlace();
                if (!place.geometry) {
                    return;
                }
                senderApartmentInput.value = '';
                senderCityInput.value = '';
                senderStateSelect.value = '';
                senderPostalCodeInput.value = '';
                senderCountrySelect.value = '';
                for (var i = 0; i < place.address_components.length; i++) {
                    var component = place.address_components[i];
                    if (component.types.indexOf('street_number') !== -1) {
                        senderStreetInput.value = component.long_name;
                    } else if (component.types.indexOf('route') !== -1) {
                        senderStreetInput.value += ' ' + component.long_name;
                    } else if (component.types.indexOf('locality') !== -1) {
                        senderCityInput.value = component.long_name;
                    } else if (component.types.indexOf('administrative_area_level_1') !== -1) {
                        senderStateSelect.value = component.long_name;
                    } else if (component.types.indexOf('postal_code') !== -1) {
                        senderPostalCodeInput.value = component.long_name;
                    } else if (component.types.indexOf('country') !== -1) {
                        senderCountrySelect.value = component.long_name;
                        senderCountrySelect.dispatchEvent(new Event('change'));
                    }
                }
            });

            senderCityAutocomplete.addListener('place_changed', function () {
                var place = senderCityAutocomplete.getPlace();
                if (!place.geometry) {
                    return;
                }
                senderStreetInput.value = '';
                senderApartmentInput.value = '';
                senderStateSelect.value = '';
                senderPostalCodeInput.value = '';
                senderCountrySelect.value = '';
                for (var i = 0; i < place.address_components.length; i++) {
                    var component = place.address_components[i];
                    if (component.types.indexOf('locality') !== -1) {
                        senderCityInput.value = component.long_name;
                    } else if (component.types.indexOf('administrative_area_level_1') !== -1) {
                        senderStateSelect.value = component.long_name;
                    } else if (component.types.indexOf('country') !== -1) {
                        senderCountrySelect.value = component.long_name;
                        senderCountrySelect.dispatchEvent(new Event('change'));
                    }
                }
            });
        }
        google.maps.event.addDomListener(window, 'load', initialize);
    </script>

</head>

<body>
    <div>
        <label for="sender_street">Street Address:</label>
        <input type="text" id="sender_street" name="sender_street">
    </div>
    <div>
        <label for="sender_apartment">Apartment, suite, etc.:</label>
        <input type="text" id="sender_apartment" name="sender_apartment">
    </div>
    <div>
        <label for="sender_city">City:</label>
        <input type="text" id="sender_city" name="sender_city" required>
    </div>
    <div>
        <label for="sender_state">State/Province:</label>
        <select id="sender_state" name="sender_state" disabled required>
        </select>
    </div>
    <div>
        <label for="sender_postal_code">Zip/Postal Code:</label>
        <input type="text" id="sender_postal_code" name="sender_postal_code" required>
        <small>Enter 3-10 alphanumeric characters (letters A-Z, numbers 0-9) only.</small>
    </div>
    <div>
        <label for="sender_country">Select Country:</label>
        <select id="sender_country" name="sender_country">
            <option value="">Select a country</option>
            <option value="United States">United States</option>
            <option value="Canada">Canada</option>
        </select>
    </div>
</body>

</html>


Solution

  • There is something wrong in your script flow, probably something related to the 3 autocomplete fields and where you "reset" or empty the states select values.

    I stripped your script down to a minimal version with only Canadian provinces and it works fine. I have tried it with several addresses in Montréal, Winnipeg and Vancouver.

    Note: you should also load the API with the language parameter and set it to English. If you don't, Autocomplete will load in different languages depending on who will be using it. States, provinces, country names and even city names (in some cases) might be returned in the user language and therefore your list would not match.

    One small change I have made is that Quebec should be spelled Québec as this is how it is returned by the API.

    function initialize() {
    
      var senderStreetInput = document.getElementById('sender_street');
      var senderStateSelect = document.getElementById('sender_state');
    
      var provinces = [
        'Alberta', 'British Columbia', 'Manitoba', 'New Brunswick', 'Newfoundland and Labrador',
        'Northwest Territories', 'Nova Scotia', 'Nunavut', 'Ontario', 'Prince Edward Island',
        'Québec', 'Saskatchewan', 'Yukon'
      ];
    
      provinces.forEach(function(province) {
        var option = document.createElement('option');
        option.value = province;
        option.textContent = province;
        senderStateSelect.appendChild(option);
      });
    
      var senderStreetAutocomplete = new google.maps.places.Autocomplete(senderStreetInput, {
        types: ['address']
      });
    
      senderStreetAutocomplete.addListener('place_changed', function() {
        var place = senderStreetAutocomplete.getPlace();
        if (!place.geometry) {
          return;
        }
    
        for (var i = 0; i < place.address_components.length; i++) {
          var component = place.address_components[i];
          if (component.types.indexOf('administrative_area_level_1') !== -1) {
            senderStateSelect.value = component.long_name;
          }
        }
      });
    }
    
    google.maps.event.addDomListener(window, 'load', initialize);
    <div>
      <label for="sender_street">Street Address:</label>
      <input type="text" id="sender_street" name="sender_street">
    </div>
    <div>
      <label for="sender_state">State/Province:</label>
      <select id="sender_state" name="sender_state">
      </select>
    </div>
    
    <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&libraries=places&language=en"></script>