Romaine M.
Romaine M.

Reputation: 371

Retrieving Postal Code with Google Maps Javascript API V3 Reverse Geocode

I'm trying to submit a query using the postal code to my DB whenever the googlemaps viewport center changes. I know that this can be done with reverse geocoding with something like:

google.maps.event.addListener(map, 'center_changed', function(){
newCenter();
});
...
function newCenter(){
var newc = map.getCenter();
geocoder.geocode({'latLng': newc}, function(results, status){
if (status == google.maps.GeocoderStatus.OK) {
  var newzip = results[0].address_components['postal_code'];
  }
});
};

Of course, this code doesn't actually work. So I was wondering how I would need to change this in order to extract the postal code from the results array. Thanks

Upvotes: 23

Views: 67738

Answers (23)

Aldo
Aldo

Reputation: 933

Just search for postal_code in all types, and return when found.

const address_components = [{"long_name": "2b","short_name": "2b","types": ["street_number"]}, { "long_name": "Louis Schuermanstraat","short_name": "Louis Schuermanstraat", "types": ["route"]},{"long_name": "Gent","short_name": "Gent","types": ["locality","political" ]},{"long_name": "Oost-Vlaanderen","short_name": "OV","types": ["administrative_area_level_2","political"]},{"long_name": "Vlaanderen","short_name": "Vlaanderen","types": ["administrative_area_level_1","political"]},{"long_name": "België","short_name": "BE","types": ["country","political"]},{"long_name": "9040","short_name": "9040","types": ["postal_code"]}];
    
// address_components = results[0]address_components

console.log({
  'object': getByGeoType(address_components),
  'short_name': getByGeoType(address_components).short_name,
  'long_name': getByGeoType(address_components).long_name,
  'route': getByGeoType(address_components, ['route']).long_name,
  'place': getByGeoType(address_components, ['locality', 'political']).long_name
});


function getByGeoType(components, type = ['postal_code']) {
  let result = null;
  $.each(components,
    function() {
      if (this.types.some(r => type.indexOf(r) >= 0)) {
        result = this;
        return false;
      }
    });
  return result;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Upvotes: 0

i think this is the most accurate solution:

zipCode: result.address_components.find(item => item.types[0] === 'postal_code').long_name;

Upvotes: 0

Rahil Wazir
Rahil Wazir

Reputation: 10142

You can also use JavaScript .find method which is similar to underscore _.find method but it is native and require no extra dependency.

const zip_code = results[0].address_components.find(addr => addr.types[0] === "postal_code").short_name;

Upvotes: 4

PavelX
PavelX

Reputation: 1

As I got it zip is the last or the one that before last. That why this is my solution

const getZip = function (arr) {
  return (arr[arr.length - 1].types[0] === 'postal_code') ? arr[arr.length - 1].long_name : arr[arr.length - 2].long_name;
};
const zip = getZip(place.address_components);

Upvotes: 0

Romaine M.
Romaine M.

Reputation: 371

Alright, so I got it. The solution is a little uglier than I'd like, and I probably don't need the last for loop, but here's the code for anyone else who needs to extract crap from address_components[]. This is inside the geocoder callback function

// make sure to initialize i
for(i=0; i < results.length; i++){
            for(var j=0;j < results[i].address_components.length; j++){
                for(var k=0; k < results[i].address_components[j].types.length; k++){
                    if(results[i].address_components[j].types[k] == "postal_code"){
                        zipcode = results[i].address_components[j].short_name;
                    }
                }
            }
    }

Upvotes: 12

webmatrix
webmatrix

Reputation: 122

I think rather than depending on the index it better checks address type key inside the component. I solved this issue by using a switch case.

      var address = '';
      var pin = '';
      var country = '';
      var state = '';
      var city = '';
      var streetNumber = '';
      var route ='';
      var place = autocomplete.getPlace(); 
      for (var i = 0; i < place.address_components.length; i++) {
        var component = place.address_components[i];
        var addressType = component.types[0];

        switch (addressType) {
            case 'street_number':
                streetNumber = component.long_name;
                break;
            case 'route':
                route = component.short_name;
                break;
            case 'locality':
                city = component.long_name;
                break;
            case 'administrative_area_level_1':
                state = component.long_name;
                break;
            case 'postal_code':
                pin = component.long_name;
                break;
            case 'country':
                country = component.long_name;
                break;
        }
       }

Upvotes: 2

imgmongelli
imgmongelli

Reputation: 41

$.each(results[0].address_components,function(index,value){
    if(value.types[0] === "postal_code"){
        $('#postal_code').val(value.long_name);
    }
});

Upvotes: 4

santillanix
santillanix

Reputation: 2014

I use this code to get "Postal code" and "locality", but you can use it to get any other field just changing the value of type:

JAVASCRIPT

var address = results[0].address_components;
var zipcode = '';
var locality = '';

for (var i = 0; i < address.length; i++) {
     if (address[i].types.includes("postal_code")){ zipcode = address[i].short_name; }    
     if (address[i].types.includes("locality")){ locality = address[i].short_name; }
}

Upvotes: 2

Dale Mugford
Dale Mugford

Reputation: 21

Romaine M. — thanks! If you just need to find the postal code in the first returned result from Google, you can do just 2 loops:

for(var j=0;j < results[0].address_components.length; j++){
    for(var k=0; k < results[0].address_components[j].types.length; k++){
        if(results[0].address_components[j].types[k] == "postal_code"){
            zipcode = results[0].address_components[j].long_name;
        }
    }
}

Upvotes: 1

Dar&#237;o Pm
Dar&#237;o Pm

Reputation: 159

It seems that nowadays it's better to get it from the restful API, simply try:

https://maps.googleapis.com/maps/api/geocode/json?latlng=40.714224,-73.961452&key=YOUR_KEY_HERE

Using an AJAX GET call works perfect!

Something like:

var your_api_key = "***";
var f_center_lat = 40.714224;
var f_center_lon = -73.961452;

$.ajax({ url: "https://maps.googleapis.com/maps/api/geocode/json?latlng="+f_center_lat+","+f_center_lon+"&key="+your_api_key,
            method: "GET"
        })
        .done(function( res ) { if (debug) console.log("Ajax result:"); console.log(res);
            var zipCode = null;
            var addressComponent = res.results[0].address_components;
            for (var x = 0 ; x < addressComponent.length; x++) {
                var chk = addressComponent[x];
                if (chk.types[0] == 'postal_code') {
                    zipCode = chk.long_name;
                }
            }
            if (zipCode) {
                //alert(zipCode);
                $(current_map_form + " #postalcode").val(zipCode);
            }
            else {
                //alert('No result found!!');
                if (debug) console.log("Zip/postal code not found for this map location.")
            }
        })
        .fail(function( jqXHR, textStatus ) {
            console.log( "Request failed (get postal code via geocoder rest api). Msg: " + textStatus );
        });

Upvotes: 0

B. Bohdan
B. Bohdan

Reputation: 529

In PHP I use this code. Almost in every conditions it works.

$zip = $data["results"][3]["address_components"];
$zip = $index[0]["short_name"];

Upvotes: 1

Ashu Ashutosh
Ashu Ashutosh

Reputation: 21

You can also use this code, this function will help to get zip on button click or onblur or keyup or keydown.

Just pass the address to this function.

use google api with valid key and sensor option removed as it doesn't required now.

function callZipAPI(addSearchZip)
{    
    var geocoder = new google.maps.Geocoder();
    var zipCode = null;

    geocoder.geocode({ 'address': addSearchZip }, function (results, status) {
        if (status == google.maps.GeocoderStatus.OK) {

            //var latitude = results[0].geometry.location.lat();
            //var longitude = results[0].geometry.location.lng();

            var addressComponent = results[0].address_components;            
            for (var x = 0 ; x < addressComponent.length; x++) {
                var chk = addressComponent[x];
                if (chk.types[0] == 'postal_code') {
                    zipCode = chk.long_name;
                }
            }
            if (zipCode) {
                alert(zipCode);
            }
            else {
                alert('No result found!!');
            }
        } else {            
            alert('Enter proper address!!');
        }
    });
}

Upvotes: 2

Ashu Ashutosh
Ashu Ashutosh

Reputation: 21

//autocomplete is the text box where u will get the suggestions for an address.

autocomplete.addListener('place_changed', function () {
//Place will get the selected place geocode and returns with the address              
//and marker information.
        var place = autocomplete.getPlace();
//To select just the zip code of complete address from marker, below loop //will help to find. Instead of y.long_name you can also use y.short_name. 
        var zipCode = null;
        for (var x = 0 ; x < place.address_components.length; x++) {
            var y = place.address_components[x];
            if (y.types[0] == 'postal_code') {
                zipCode = y.long_name;
            }
        }
    });

Upvotes: 0

Ray Myers
Ray Myers

Reputation: 11

Using JSONPath, it's easily done with one line of code:

var zip = $.results[0].address_components[?(@.types=="postal_code")].long_name;

Upvotes: 1

user6009947
user6009947

Reputation: 1

 return $http.get('//maps.googleapis.com/maps/api/geocode/json', {
            params: {
                address: val,
                sensor: false
            }
        }).then(function (response) {
           var model= response.data.results.map(function (item) {
               // return item.address_components[0].short_name;
               var short_name;
             var st=  $.each(item.address_components, function (value, key) {
                    if (key.types[0] == "postal_code") {
                        short_name= key.short_name;
                    }
                });
             return short_name;

            });
                return model;
        });

Upvotes: 0

Sunny
Sunny

Reputation: 952

Using Jquery

  • You cant be sure in which location in the address_components array the postal code is stored. Sometimes in address_components.length - 1 > pincode may not be there. This is true in "Address to latlng" geocoding.
  • You can be sure that Postal code will contain a "postal_code" string. So best way is to check for that.
   var postalObject = $.grep(results[0].address_components, function(n, i) {
                                    if (n.types[0] == "postal_code") {
                                        return n;
                                    } else {
                                        return null;
                                    }
                                });

                                $scope.query.Pincode = postalObject[0].long_name;

Upvotes: 0

Tuco
Tuco

Reputation: 1630

What I've realized so far is that in most cases the ZIPCODE is always the last value inside each returned address, so, if you want to retrieve the very first zipcode (this is my case), you can use the following approach:

var address = results[0].address_components;
var zipcode = address[address.length - 1].long_name;

Upvotes: 23

Rene Vazquez
Rene Vazquez

Reputation: 1

This simple code works for me

for (var i = 0; i < address.length; i++) {
        alert(address[i].types);
        if (address[i].types == "postal_code")
            $('#postalCode').val(address[i].long_name);
        if (address[i].types == "")
            $('#country').val(address[i].short_name);
    }

Upvotes: 0

EMuentes
EMuentes

Reputation: 562

Using JQuery?

var searchAddressComponents = results[0].address_components,
    searchPostalCode="";

$.each(searchAddressComponents, function(){
    if(this.types[0]=="postal_code"){
        searchPostalCode=this.short_name;
    }
});

short_name or long_name will work above
the "searchPostalCode" var will contain the postal (zip?) code IF and only IF you get one from the Google Maps API.

Sometimes you DO NOT get a "postal_code" in return for your query.

Upvotes: 12

Jeff S
Jeff S

Reputation: 553

You can do this pretty easily using the underscore.js libraray: http://documentcloud.github.com/underscore/#find

_.find(results[0].address_components, function (ac) { return ac.types[0] == 'postal_code' }).short_name

Upvotes: 14

user1116928
user1116928

Reputation: 149

places.getDetails( request_details, function(results_details, status){

                // Check if the Service is OK
                if (status == google.maps.places.PlacesServiceStatus.OK) {                  

                    places_postal           = results_details.address_components
                    places_phone            = results_details.formatted_phone_number
                    places_phone_int        = results_details.international_phone_number
                    places_format_address   = results_details.formatted_address
                    places_google_url       = results_details.url
                    places_website          = results_details.website
                    places_rating           = results_details.rating

                    for (var i = 0; i < places_postal.length; i++ ) {
                        if (places_postal[i].types == "postal_code"){
                            console.log(places_postal[i].long_name)
                        }
                    }

                }
            });

This seems to work very well for me, this is with the new Google Maps API V3. If this helps anyone, write a comment, i'm writing my script as we speak... so it might change.

Upvotes: 1

learntoswim
learntoswim

Reputation: 21

This takes only two for loops. The "results" array gets updated once we found the first "type" to be "postal_code".

It then updates the original array with the newly found array set and loops again.

            var i, j,
            result, types;

            // Loop through the Geocoder result set. Note that the results
            // array will change as this loop can self iterate.
            for (i = 0; i < results.length; i++) {

                result = results[i];

                types = result.types;

                for (j = 0; j < types.length; j++) {

                    if (types[j] === 'postal_code') {

                        // If we haven't found the "long_name" property,
                        // then we need to take this object and iterate through
                        // it again by setting it to our master loops array and 
                        // setting the index to -1
                        if (result.long_name === undefined) {
                            results = result.address_components;
                            i = -1;
                        }
                        // We've found it!
                        else {
                            postcode = result.long_name;
                        }

                        break;

                    }

                }

            }

Upvotes: 2

JFrancis
JFrancis

Reputation: 365

In a word, that's a lot of effort. At least with the v2 API, I could retrieve those details thusly:

var place = response.Placemark[0];
var point = new GLatLng(place.Point.coordinates[1], place.Point.coordinates[0]);

myAddress = place.AddressDetails.Country.AdministrativeArea.SubAdministrativeArea.Locality.Thoroughfare.ThoroughfareName

myCity = place.AddressDetails.Country.AdministrativeArea.SubAdministrativeArea.Locality.LocalityName

myState = place.AddressDetails.Country.AdministrativeArea.AdministrativeAreaName

myZipCode = place.AddressDetails.Country.AdministrativeArea.SubAdministrativeArea.Locality.PostalCode.PostalCodeNumber

There has got to be a more elegant way to retrieve individual address_components without going through the looping jujitsu you just went through.

Upvotes: 0

Related Questions