Автозаполнение Google - введите, чтобы выбрать


80

У меня есть Google Autocomplete, настроенный для текстового поля HTML-формы, и он отлично работает.

Однако, когда появляется список предложений, и вы используете стрелки для прокрутки и выбора с помощью ввода, он отправляет форму, хотя есть еще поля для заполнения. Если вы щелкаете, чтобы выбрать предложение, оно работает нормально, но нажатие Enter отправляет .

Как я могу это контролировать? Как я могу остановить ввод от отправки формы, а вместо этого выбрать предложение из автозаполнения?

Благодаря! {S}

Ответы:


110

Вы можете использовать, preventDefaultчтобы остановить отправку формы при нажатии ввода, я использовал что-то вроде этого:

  var input = document.getElementById('inputId');
  google.maps.event.addDomListener(input, 'keydown', function(event) { 
    if (event.keyCode === 13) { 
        event.preventDefault(); 
    }
  }); 

2
Это всегда отменит отправку из поля. Мне нужно только отменить отправку, если пользователь нажал ввод, чтобы выбрать опцию автозаполнения.
А. Матиас Кесада

1
Работает как драгоценный камень. Нажатие и выбор опции автозаполнения из списка с вводом больше не отправляет форму.
Эрик Л.

Это больше не шаблон, чем решение. То же, что и использование обработчика onClick для отправки формы вместо обработчика onSubmit. Enter должен отправить форму.
Алекс Федосеев

4
Я использовал в keyupтечение последнего получаса , пытаясь решить мою проблему, которую вы сделали. Итак, люди, не используйте, keyupчтобы поймать отправленные формы
Нико

52

Использование обработки событий Google кажется правильным решением, но у меня это не работает. Это решение jQuery работает для меня:

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

.pac-container- это div, содержащий совпадения с автозаполнением. Идея состоит в том, что, когда совпадения видны, клавиша Enter просто выбирает активное совпадение. Но когда совпадения скрыты (т. Е. Место выбрано), он отправит форму.


прекрасно работает, так что спасибо. просто и эффективно.
luke_mclachlan 05

Наверное, самое элегантное решение. Спасибо!
Николай Трайков

но разве это не позволит вводить форму в пустое поле? перед выбором адреса?
amosmos

1
Это не работает в Chrome. Похоже, что события клавиш Chrome не обнаруживают Enter, если ввод находится внутри формы.
Бруно

1
Единственным недостатком этого решения является то, что если Google решит изменить HTML-код, который они вводят на вашу страницу, и переименовать .pac-containerво что-то другое, это сломается.
Джастин Таннер

21

Я объединил первые два ответа от @sren и @mmalone, чтобы получить следующее:

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

отлично работает на странице. предотвращает отправку формы, когда виден контейнер предложений (.pac-container). Итак, теперь опция из раскрывающегося списка автозаполнения выбирается, когда пользователи нажимают клавишу ввода, и им нужно нажать ее снова, чтобы отправить форму.

Моя основная причина использования этого обходного пути заключается в том, что я обнаружил, что если форма отправляется сразу после выбора опции с помощью клавиши ввода, значения широты и долготы не передаются достаточно быстро в их скрытые элементы формы.

Все заслуги оригинальных ответов.


7

Это сработало для меня:

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();

  }

});

Может быть легко преобразован из ES6 в любой код, совместимый с браузером.


Мне нравится ваш ответ, но мне пришлось немного подправить его, чтобы заставить его работать. Выложил свое решение.
Schulwitz

4

Проблема с ответом @ sren заключалась в том, что он всегда блокирует событие отправки. Мне понравился ответ @ mmalone, но он вел себя случайным образом, так как иногда, когда я нажимал, ENTERчтобы выбрать местоположение, обработчик запускался после того, как контейнер был скрыт. Итак, вот что я в итоге сделал

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>

Флаг гарантирует, что, если местоположение изменяется и пользователь нажимает клавишу ввода, событие блокируется. В конце концов, флаг устанавливается событием falseкарты Google place_changed, которое затем позволяет отправить форму при нажатии клавиши ввода.


Этот код действительно сработал для меня, спасибо за ваши усилия!
Аймал Хан

Этот код избегает отправки, если пользователь пишет, нажимает ввод, а затем стрелку вниз (или любую клавишу, которая не запускает автозаполнение). После этого возврат блокируется.
Natxet

1

Вот простой код, который у меня хорошо сработал (без jquery).

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

Этот фрагмент кода, следуя приведенному выше коду, используется для реализации автозаполнения карт Google (с функцией клавиши Enter или без нее, о которой идет речь в этом вопросе):

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 (названный выше в первой части кода) определил:

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

Этот код заставляет поле автозаполнения карт Google выбирать любой элемент, который пользователь выбирает с помощью клавиши со стрелкой вниз. Когда пользователь выбирает параметр нажатием клавиши Enter, ничего не происходит. Пользователь должен снова нажать Enter, чтобы вызвать onSubmit () или другую команду.


0

Я подправил код Алекса, потому что он сломался в браузере. Это идеально подходит для меня:

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]);
    }
}

0

Я пробовал приведенные выше короткие ответы, но они не сработали для меня, а длинные ответы я не хотел их пробовать, поэтому я создал следующий код, который мне очень понравился. См. Демонстрацию

Предположим, это ваша форма:

<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>

Тогда следующий код javascript решит проблему:

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;
    }
});

А вот как выглядит полный код на HTML-странице (обратите внимание, что вам нужно заменить YOUR_API_KEYключ API Google):

<!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>

0
$("#myinput").on("keydown", function(e) {
if (e.which == 13) {

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

}

Используйте, $('.pac-item:first').trigger('click');если хотите выбрать первый результат


0

Сделать это можно в ванили:

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();
     }
 })
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.