SERPRO
SERPRO

Reputation: 10067

Filter results from Google Autocomplete

Is there a way to get the results from Google Autocomplete API before it's displayed below the input? I want to show results from any country except U.S.A.

I found this question: Google Maps API V3 - Anyway to retrieve Autocomplete results instead of dropdown rendering it? but it's not useful, because the method getQueryPredictions only returns 5 elements.

This is an example with UK and US Results: http://jsfiddle.net/LVdBK/

Is it possible?

Upvotes: 4

Views: 3051

Answers (1)

daajason
daajason

Reputation: 56

I used the jquery autocomplete widget and called the google methods manually.

For our case, we only wanted to show addresses in Michigan, US. Since Google doesn't allow filtering out responses to that degree you have to do it manually.

  1. Override the source function of the jquery autocomplete
  2. Call the google autocompleteService.getQueryPredictions method
  3. Filter out the results you want and return them as the "response" callback of the jquery autocomplete.

Optionally, if you need more detail about the selected item from Google, override the select function of the jquery autocomplete and make a call to Google's PlacesService.getDetails method.

The below assumes you have the Google api reference with the "places" library.

<script src="https://maps.googleapis.com/maps/api/js?key=[yourKeyHere]&libraries=places&v=weekly" defer></script>
var _autoCompleteService; // defined globally in script
var _placesService; // defined globally in script

//...

// setup autocomplete wrapper for google places 

// starting point in our city
    var defaultBounds = new google.maps.LatLngBounds(
         new google.maps.LatLng('42.9655426','-85.6769166'),
         new google.maps.LatLng('42.9655426','-85.6769166'));

   
    if (_autoCompleteService == null) {
        _autoCompleteService = new google.maps.places.AutocompleteService();
    }
    
    $("#CustomerAddress_Street").autocomplete({
        minLength: 2,
        source: function (request, response) {
            if (request.term != '') {
                var googleRequest = {
                    input: request.term,
                    bounds: defaultBounds,
                    types: ["geocode"],
                    componentRestrictions: { 'country': ['us'] },
                    fields: ['geometry', 'formatted_address']
                }
                _autoCompleteService.getQueryPredictions(googleRequest, function (predictions) {
                    var michiganOnly = new Array(); // array to hold only addresses in Michigan
                
                    for (var i = 0; i < predictions.length; i++) {
                        if (predictions[i].terms.length > 0) {
                            // find the State term. Could probably assume it's predictions[4], but not sure if it is guaranteed.
                            for (var j = 0; j < predictions[i].terms.length; j++) {
                                if (predictions[i].terms[j].value.length == 2) {
                                    if (predictions[i].terms[j].value.toUpperCase() == 'MI') {
                                        michiganOnly.push(predictions[i]);
                                    }
                                }
                            }
                        }
                    }
                    response(michiganOnly);
                });
            }
        },
        select: function (event, ui) {
            if (ui != null) {
                var item = ui.item;
                var request = {
                    placeId: ui.item.place_id
                }

                if (_placesService == null) {
                    $("body").append("<div id='GoogleAttribution'></div>"); // PlacesService() requires a field to put it's attribution image in. For now, just put on on the body
                    _placesService = new google.maps.places.PlacesService(document.getElementById('GoogleAttribution'));
                }
                _placesService.getDetails(request, function (result, status) {
                    if (result != null) {
                        const place = result;
                        
                        if (!place.geometry) {
                            // User entered the name of a Place that was not suggested and
                            // pressed the Enter key, or the Place Details request failed.
                            //window.alert("No details available for input: '" + place.name + "'");
                            return;
                        }
                        else {
                            var latitude = place.geometry.location.lat();
                            var longitude = place.geometry.location.lng();
                        // do something with Lat/Lng
                        }
                    }
                });
            }
        }

    }).autocomplete("instance")._renderItem = function (ul, item) {
    // item is the prediction object returned from our call to getQueryPredictions
    // return the prediction object's "description" property or do something else
        return $("<li>")
            .append("<div>" + item.description + "</div>")
            .appendTo(ul);
    };
    $("#CustomerAddress_Street").autocomplete("instance")._renderMenu = function (ul, items) {
    // Google's terms require attribution, so when building the menu, append an item pointing to their image
        var that = this;
        $.each(items, function (index, item) {
            that._renderItemData(ul, item);
        });
        $(ul).append("<li class='ui-menu-item'><div style='display:flex;justify-content:flex-end;'><img src='https://maps.gstatic.com/mapfiles/api-3/images/powered-by-google-on-white3.png' /></div></li>")
    }

Upvotes: 3

Related Questions