Google Autocomplete - Geben Sie zur Auswahl ein

80

Ich habe Google Autocomplete für ein Textfeld eines HTML-Formulars eingerichtet und es funktioniert einwandfrei.

Wenn jedoch die Liste der Vorschläge angezeigt, und Sie mit den Pfeilen zu blättern und wählen Sie Eingabe verwenden, ist es das Formular abschickt, obwohl es immer noch Boxen sind in zu füllen. Wenn Sie einen Vorschlag auszuwählen klicken es gut funktioniert, aber das Pressen eingeben vorträgt .

Wie kann ich das kontrollieren? Wie kann ich verhindern, dass die Eingabe das Formular sendet, und stattdessen einen Vorschlag aus der automatischen Vervollständigung auswählen?

Vielen Dank! {S}

kinkersnick
quelle

Antworten:

110

Sie können verwenden preventDefault, um das Senden des Formulars zu stoppen, wenn die Eingabetaste gedrückt wird. Ich habe Folgendes verwendet:

  var input = document.getElementById('inputId');
  google.maps.event.addDomListener(input, 'keydown', function(event) { 
    if (event.keyCode === 13) { 
        event.preventDefault(); 
    }
  }); 
sren
quelle
2
Dadurch wird die Übermittlung aus dem Feld immer abgebrochen. Ich brauche es nur, um das Senden abzubrechen, wenn der Benutzer auf Intro gedrückt hat, um eine Option für die automatische Vervollständigung auszuwählen.
A. Matías Quezada
1
Funktioniert wie ein Juwel. Wenn Sie die Option zum automatischen Vervollständigen aus der Liste mit der Eingabetaste auswählen, wird das Formular nicht mehr gesendet.
Eric L.
Dies ist eher ein Unti-Muster als eine Lösung. Entspricht der Verwendung des onClick-Handlers zum Senden des Formulars anstelle des onSubmit-Handlers. Enter sollte das Formular senden.
Alex Fedoseev
4
Ich habe in keyupder letzten halben Stunde versucht, mein Problem zu lösen, was Sie auch getan haben. Also, Leute, benutzt es nicht keyup, um Formulareingaben zu fangen
Nico
52

Die Verwendung der Google-Ereignisbehandlung scheint die richtige Lösung zu sein, funktioniert aber bei mir nicht. Diese jQuery-Lösung funktioniert für mich:

$('#inputId').keydown(function (e) {
  if (e.which == 13 && $('.pac-container:visible').length) return false;
});

.pac-containerist das Div, das die Autocomplete-Übereinstimmungen enthält. Die Idee ist, dass, wenn die Übereinstimmungen sichtbar sind, die Eingabetaste nur die aktive Übereinstimmung auswählt. Wenn die Übereinstimmungen jedoch ausgeblendet sind (dh ein Ort ausgewählt wurde), wird das Formular gesendet.

Mmalone
quelle
funktioniert wunderbar, also danke. einfach und effektiv.
luke_mclachlan
Wahrscheinlich die eleganteste Lösung. Vielen Dank!
Nikolay Traykov
aber würde das nicht eine Eingabe erlauben, die das Formular in einem leeren Feld sendet? vor der Auswahl einer Adresse?
Amosmos
1
Dies funktioniert in Chrome nicht. Es sieht so aus, als würden Chrome-Schlüsselereignisse die Eingabetaste nicht erkennen, wenn sich die Eingabe in einem Formular befindet.
Bruno
1
Der einzige Nachteil dieser Lösung ist, dass wenn Google beschließt, den HTML-Code zu ändern, der in Ihre Seite eingefügt und .pac-containerin etwas anderes umbenannt wird, dies nicht funktioniert.
Justin Tanner
21

Ich habe die ersten beiden Antworten von @sren und @mmalone zusammengeführt, um dies zu erzeugen:

var input= document.getElementById('inputId');
google.maps.event.addDomListener(input, 'keydown', function(e) { 
    if (e.keyCode == 13 && $('.pac-container:visible').length) { 
        e.preventDefault(); 
    }
}); 

funktioniert perfekt auf der Seite. verhindert, dass das Formular gesendet wird, wenn der Vorschlagscontainer (.pac-container) sichtbar ist. Daher wird jetzt eine Option aus der Dropdown-Liste für die automatische Vervollständigung ausgewählt, wenn die Benutzer die Eingabetaste drücken und sie erneut drücken müssen, um das Formular zu senden.

Mein Hauptgrund für die Verwendung dieser Problemumgehung ist, dass ich festgestellt habe, dass beim Senden des Formulars nach Auswahl einer Option über die Eingabetaste die Breiten- und Längengrade nicht schnell genug an die ausgeblendeten Formularelemente übergeben wurden.

Alle Anerkennung für die ursprünglichen Antworten.

luke_mclachlan
quelle
7

Dieser hat für mich gearbeitet:

google.maps.event.addDomListener(input, 'keydown', e => {

  // If it's Enter
  if (e.keyCode === 13) {

    // Select all Google's dropdown DOM nodes (can be multiple)
    const googleDOMNodes = document.getElementsByClassName('pac-container');

    // Check if any of them are visible (using ES6 here for conciseness)
    const googleDOMNodeIsVisible = (
      Array.from(googleDOMNodes).some(node => node.offsetParent !== null)
    );

    // If one is visible - preventDefault
    if (googleDOMNodeIsVisible) e.preventDefault();

  }

});

Kann einfach von ES6 in einen beliebigen browserkompatiblen Code konvertiert werden.

Alex Fedoseev
quelle
Ich mag deine Antwort, aber ich musste sie ein wenig optimieren, damit sie funktioniert. Hat meine Lösung gepostet.
Schulwitz
4

Das Problem, das ich mit der Antwort von @ sren hatte, war, dass es das Submit-Ereignis immer blockiert. Ich mochte die Antwort von @ mmalone, aber sie verhielt sich zufällig, da manchmal, wenn ich drückte ENTER, um den Ort auszuwählen, der Handler lief, nachdem der Container versteckt war. Also, hier ist, was ich letztendlich getan habe

var location_being_changed,
    input = document.getElementById("js-my-input"),
    autocomplete = new google.maps.places.Autocomplete(input),
    onPlaceChange = function () {
        location_being_changed = false;
    };

google.maps.event.addListener( this.autocomplete,
                               'place_changed',
                               onPlaceChange );

google.maps.event.addDomListener(input, 'keydown', function (e) {
    if (e.keyCode === 13) {
        if (location_being_changed) {
            e.preventDefault();
            e.stopPropagation();
        }
    } else {
        // means the user is probably typing
        location_being_changed = true;
    }
});

// Form Submit Handler
$('.js-my-form').on('submit', function (e) {
    e.preventDefault();
    $('.js-display').text("Yay form got submitted");
});
<p class="js-display"></p>
<form class="js-my-form">
    <input type="text" id="js-my-input" />
    <button type="submit">Submit</button>
</form>

<!-- External Libraries -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="//maps.googleapis.com/maps/api/js?sensor=false&libraries=places"></script>

Das Flag stellt sicher, dass das Ereignis blockiert wird, wenn der Standort geändert wird und Benutzertreffer eingegeben werden. Schließlich wird das Flag falsedurch das place_changedEreignis von Google Map gesetzt , wodurch das Formular beim Drücken der Eingabetaste gesendet werden kann.

Mudassir Ali
quelle
Dieser Code hat tatsächlich für mich funktioniert, danke für die Mühe!
Aimal Khan
Dieser Code vermeidet das Senden, wenn der Benutzer schreibt, die Eingabetaste drückt und dann den Pfeil nach unten drückt (oder eine Taste, die keine automatische Vervollständigung auslöst). Danach wird die Rückgabe blockiert.
Natxet
1

Hier ist ein einfacher Code, der für mich gut funktioniert hat (verwendet keine JQuery).

const googleAutcompleteField = this.renderer.selectRootElement(this.elem.nativeElement);
this.selectOnEnter(googleAutcompleteField);

Dieser Code wird, um dem obigen Code zu folgen, verwendet, um die automatische Vervollständigung von Google Maps zu implementieren (mit oder ohne die in dieser Frage gesuchte Eingabetaste):

this.autocomplete = new google.maps.places.Autocomplete(googleAutcompleteField, this.googleMapsOptions);
this.autocomplete.setFields(['address_component', 'formatted_address', 'geometry']);
this.autocomplete.addListener('place_changed', () => {
  this.zone.run(() => {
    this.googleMapsData.emit([this.autocomplete.getPlace()]);
  })
})

selectOnEnter (oben im ersten Code aufgerufen) definiert:

selectOnEnter(inputField) {
  inputField.addEventListener("keydown", (event) => {
    const selectedItem = document.getElementsByClassName('pac-item-selected');
    if (event.key == "Enter" && selectedItem.length != 0) {
      event.preventDefault();
    }
  })
}

Mit diesem Code wählt das Feld für die automatische Vervollständigung von Google Maps das Element aus, das der Benutzer mit dem Abwärtspfeil auswählt. Sobald der Benutzer eine Option durch Drücken der Eingabetaste auswählt, geschieht nichts mehr. Der Benutzer muss erneut die Eingabetaste drücken, um onSubmit () oder einen anderen Befehl auszulösen

coder101
quelle
0

Ich habe Alex 'Code optimiert, weil er im Browser kaputt gegangen ist. Das funktioniert perfekt für mich:

google.maps.event.addDomListener(
    document.getElementById('YOUR_ELEMENT_ID'),
    'keydown',
    function(e) {
          // If it's Enter
          if (e.keyCode === 13) {
            // Select all Google's dropdown DOM nodes (can be multiple)
            const googleDOMNodes = document.getElementsByClassName('pac-container');
            //If multiple nodes, prevent form submit.
            if (googleDOMNodes.length > 0){
                e.preventDefault();
            }
            //Remove Google's drop down elements, so that future form submit requests work.
            removeElementsByClass('pac-container');
          }
    }
);

function removeElementsByClass(className){
    var elements = document.getElementsByClassName(className);
    while(elements.length > 0){
        elements[0].parentNode.removeChild(elements[0]);
    }
}
schulwitz
quelle
0

Ich habe die obigen kurzen Antworten ausprobiert, aber sie haben bei mir nicht funktioniert, und die langen Antworten wollte ich nicht ausprobieren. Deshalb habe ich den folgenden Code erstellt, der für mich ziemlich gut funktioniert hat. Siehe Demo

Angenommen, dies ist Ihr Formular:

<form action="" method="">
      <input type="text" name="place" id="google-places-searchbox" placeholder="Enter place name"><br><br>
      <input type="text" name="field-1" placeholder="Field 1"><br><br>
      <input type="text" name="field-2" placeholder="Field 2"><br><br>
      <button type="submit">Submit</button>
</form>

Dann löst der folgende Javascript-Code das Problem:

var placesSearchbox = $("#google-places-searchbox");

placesSearchbox.on("focus blur", function() {
    $(this).closest("form").toggleClass('prevent_submit');
});

placesSearchbox.closest("form").on("submit", function(e) {
    if (placesSearchbox.closest("form").hasClass('prevent_submit')) {
        e.preventDefault();
        return false;
    }
});

Und so sieht der vollständige Code auf der HTML-Seite aus (Beachten Sie, dass Sie den Code YOUR_API_KEYdurch Ihren Google API-Schlüssel ersetzen müssen ):

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>Prevent form submission when choosing a place from google places autocomplete searchbox</title>
</head>
<body>
  <form action="" method="">
      <input type="text" name="place" id="google-places-searchbox" placeholder="Enter place name"><br><br>
      <input type="text" name="field-1" placeholder="Field 1"><br><br>
      <input type="text" name="field-2" placeholder="Field 2"><br><br>
      <button type="submit">Submit</button>
  </form>

  <!-- jQuery -->
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

  <!-- Google Maps -->
  <!-- Note that you need to replace the next YOUR_API_KEY with your api key -->
  <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places"
     async defer></script>
  <script>
    var input = document.getElementById("google-places-searchbox");
    var searchBox = new google.maps.places.SearchBox(input);

    var placesSearchbox = $("#google-places-searchbox");

    placesSearchbox.on("focus blur", function() {
        $(this).closest("form").toggleClass('prevent_submit');
    });

    placesSearchbox.closest("form").on("submit", function(e) {
        if (placesSearchbox.closest("form").hasClass('prevent_submit')) {
            e.preventDefault();
            return false;
        }
    });
  </script>
</body>
</html>
Amr
quelle
0
$("#myinput").on("keydown", function(e) {
if (e.which == 13) {

if($(".pac-item").length>0)
        {
            $(".pac-item-selected").trigger("click");
}

}

Verwenden $('.pac-item:first').trigger('click');Sie diese Option, wenn Sie das erste Ergebnis auswählen möchten

Mool Singh
quelle
0

Sie können es in Vanille tun:

element.addEventListener('keydown', function(e) {
    const gPlaceChoices = document.querySelector('.pac-container')
    // No choices element ? 
    if (null === gPlaceChoices) {
        return
    }
    // Get choices visivility
    let visibility = window.getComputedStyle(gPlaceChoices).display
    // In this case, enter key will do nothing
    if ('none' !== visibility && e.keyCode === 13) {
        e.preventDefault();
     }
 })
Digivia
quelle