Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Google Places Autocomplete SearchBox: How to control (enable/disable) predictions

Is it possible to control (enable/disable) Google Places Autocomplete SearchBox (google.maps.places.SearchBox) service predictions?

Or in other words: is it possible to temporarily detach HTML input element from Autocomplete SearchBox service and then reattach it?

The thing is that I display service results just bellow HTML input element attached to SearchBox service. Problem is that after results are displayed and user focuses back on the input element, predictions are displayed over results and obscure their view. I would like to disable predictions until text in input element is changed by the user.

enter image description here

EDIT 26/Aug/2016:

Disable predictions is currently not supported by the Javascript API. Therefore I have just opened a feature request on Google. If you are interested in the feature please vote for it: Autocomplete SearchBox - Control (enable/disable) predictions..

EDIT 07/Sep/2016 - bounty award update:

Thanks to all of you who participated in answering and also in promoting the question.

Primary objective of the award was to find solution using currently available means. I am afraid this did not happen so I decided not to award the bounty.

Although none of answers bellow provides a solution, each provides some sort of lead, so thank you! Maybe those leads will point to a solution in future.

Secondary objective of the award (although not communicated directly) was to promote Autocomplete SearchBox - Control (enable/disable) predictions feature request. Its status changed to NeatIdea and has been assigned internal tracking number. It is a good sign.

like image 909
Michal Foksa Avatar asked Aug 24 '16 13:08

Michal Foksa


2 Answers

What you can do is, After the user selects the place, you can add a class disabled to that input field.., This will help you enable/disable predictions based on class name.

And where you have the autocomplete code, you can wrap it within if else statement.

let field = document.getElementById('location');
if ( field.className.indexOf('disabled') > -1 ) {
  google.maps.event.clearInstanceListeners(field);
}
else {

  let autocomplete = new google.maps.places.Autocomplete( field, {types: ['geocode']} );
  autocomplete.addListener('place_changed', () => {
    let place = autocomplete.getPlace();
    let filed_val = field.value; // incase you need it
    field.classList.add('disabled');
  });

}

This will remove the autocomplete after user selects a place.. and later if you want, you can remove the disabled class from this field and it will work again.

like image 90
Dhruv Kumar Jha Avatar answered Nov 06 '22 12:11

Dhruv Kumar Jha


My solution in AngularJS – it is an extract of from a directive.

.pac-contained is created after instance of an Autocomplete service is created, e.g.: new google.maps.places.Autocomplete(…) or new google.maps.places.SearchBox(…).

What I do is to find just created .pac-container in the document, store its reference and mark that container as already processes (by adding an arbitrary class .predictions-control on it). "Marking" the container is needed only when more than one .pac-container is expected to be present in application.

Now with the reference I can control visibility (hide or show) of the .pac-contained with predictions.

// Container element with predictions.
var pacContainer = null;

/***
 * Find predictions container without predictions-control class set.
 * Then set  predictions-control class to it and convert it into
 * Angular's jqLite object.
 * @return {jqLite object} - container or null when not found.
 */
function getPredictionsContainer() {
    // Get div.pac-container without predictions-control class.
    var e = document.querySelector('div.pac-container:not(.predictions-control)');
    if (e){
        var container = angular.element(e);
        container.addClass('predictions-control');
        console.log('predictions-control: Container found.');
        return container;
    } else {
        console.warn('predictions-control: Container not found!');
    }
    return null;
} // getPredictionsContainer

/***
 * Loop in 50ms intervals until container is found.
 */
function untilContainerFound(){
    pacContainer = getPredictionsContainer();
    if (pacContainer == null){
        $timeout(untilContainerFound, 50);
    }
} // untilContainerFound

this.init = function() {
    untilContainerFound();
}; // this.init

/***
 * Prevent predictions to be displayed when user clicks on the
 * input element. It is achieved by adding ng-hide CSS class to
 * predictions container. Predictions container is identified by
 * ".pac-container" CSS class selector.
 */
this.hidePredictions = function() {
    // If predictions container was not found at directive
    // initialization try to find it now.
    if (pacContainer === null){
        pacContainer = getPredictionsContainer();
    }
    if (pacContainer){
        console.log('predictions-control: Hiding predictions.');
        pacContainer.addClass('ng-hide');
    } else {
        console.warn('predictions-control: Container not found!');
    }
}; // this.hidePredictions

/***
 * Show predictions again by removing ng-hide CSS class from
 * predictions container.
 */
this.showPredictions = function() {
    console.log('predictions-control: Showing predictions.');
    if (pacContainer){
        pacContainer.removeClass('ng-hide');
    }
}; // this.showPredictions

Call init() right after service instance is created:

// Create SearchBox service for auto completing search terms.
autocomplete = new google.maps.places.SearchBox( inputElem[0] );
// OR
// autocomplete = new google.maps.places.Autocomplete( ..... );
autocomplete .addListener('places_changed', callback);

predictionsCtrl.init();

Note: As long as it is guaranteed that two Autocomplete services are not created at the same time (e.g.: each service is on different tab) or can wait with creation of next service until .pac-container for previous service is found, it reliably works even with multiple instances of Autocomplete service.

like image 1
Michal Foksa Avatar answered Nov 06 '22 13:11

Michal Foksa