Как я могу получить событие изменения для datalist?

Я использую список данных и мне нужно определить, когда пользователь выбирает что-то из выпадающего списка. Подобный вопрос был задан, НО мне это нужно, чтобы событие запускалось ТОЛЬКО, когда пользователь выбирает что-то из списка данных. Если они вводят что-то во ввод, то я НЕ хочу, чтобы событие сработало. (Обратите внимание в принятом ответе на вопрос, который я связал, что они связывают входные данные, а это не то, что я хочу). Я пытался (без успеха):

<datalist>
    <option>Option 1 Here</option> 
    <option>Option 2 Here</option>
</datalist>


$(document).on('change', 'datalist', function(){
   alert('hi');
});

РЕДАКТИРОВАТЬ: Этот вопрос отличается от предложенного вопроса, потому что это совершенно другой вопрос.

9 ответов

Решение

Вы можете вручную проверить это на изменение. Но вам нужно проверить изменение ввода данных.

$(document).on('change', 'input', function(){
    var options = $('datalist')[0].options;
    var val = $(this).val();
    for (var i=0;i<options.length;i++){
       if (options[i].value === val) {
          alert(val);
          break;
       }
    }
});

FIDDLE

В браузере со свойством inputType в InputEvent вы можете использовать его для фильтрации любых нежелательных событий onInput. Это "insertReplacementText" в Firefox 81 и null для Chrome/Edge 86. Если вам нужно поддерживать IE11, вам нужно будет проверить правильность значения.

         document.getElementById("browser")
  .addEventListener("input", function(event){
        if(event.inputType == "insertReplacementText" || event.inputType == null) {
          document.getElementById("output").textContent =  event.target.value;
          event.target.value = "";
    }
})
         <label for="browser">Choose your browser from the list:</label>
<input list="browsers" name="browser" id="browser">
<datalist id="browsers">
  <option value="Edge">
  <option value="Firefox">
  <option value="Chrome">
  <option value="Opera">
  <option value="Safari">
</datalist>
<div id="output">
</div>

У решений, прежде всего, есть большая проблема. Если у специалиста по данным есть вариант (например) «боб» и «бобби», как только кто-то набирает «боб», он сразу же говорит, что это то же самое, что и нажатие «боб» ... типа "бобби"?

Для лучшего решения нам нужна дополнительная информация. При прослушивании события 'input' в поле ввода:

В браузерах на основе Chromium при вводе, удалении, возврате, вырезании, вставке и т. Д. В поле ввода событие, которое передается обработчику, является событием, тогда как при выборе параметра из списка данных событие просто ан Event тип со свойством typeчто равняется «входу». (Это также верно во время автозаполнения, по крайней мере, с BitWarden).

Таким образом, вы можете прослушать событие 'input' и проверить, является ли оно экземпляром, чтобы определить, было ли оно от автозаполнения (что, я думаю, должно быть разрешено, поскольку в большинстве случаев автозаполнение не заполняет эти типы полей, и если они делают, это обычно правильный выбор) / выбор даталиста.

Однако в Firefox все по-другому. Он по-прежнему обеспечивает InputEvent, но у него есть inputTypeсвойство со значением insertReplacementText, которое мы также можем использовать. Автозаполнение делает то же самое, что и браузеры Chromium.

Итак, вот лучшее решение:

      $('#yourInput').on('input', function(){
    if (
        !(e instanceof InputEvent) ||
        e.inputType === 'insertReplacementText')
    ) {
        // determine if the value is in the datalist. If so, someone selected a value in the list!
    }
});

Я бы хотел, чтобы в браузерах была такая же реализация, в которой был тип / свойство события, которое было исключительным для выбора списка данных, но они этого не делают, поэтому это лучшее, что у меня есть. Я не тестировал это в Safari (у меня сейчас нет доступа или времени), поэтому вам, вероятно, стоит взглянуть на него и посмотреть, такой же ли он или есть другие отличительные отличия.

Оптимизированное решение

$("input").on('input', function () {
    var inputValue = this.value;
    if($('datalist').find('option').filter(function(){
        return this.value == inputVal;        
    }).length) {
        //your code as per need
        alert(this.value);
    }
});

Пожалуйста, посмотрите на ваше решение, это хорошо идти. Посмотрите на демо

$(document).on('change', 'input', function(){
    var optionslist = $('datalist')[0].options;
    var value = $(this).val();
    for (var x=0;x<optionslist.length;x++){
       if (optionslist[x].value === value) {
          //Alert here value
          alert(value);
          break;
       }
    }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input list="data">
<datalist id="data">
    <option value='1'>Option 1 Here</option> 
    <option value='2'>Option 2 Here</option>
</datalist>

и др /c1z0bnsm/7/

Больше Оптимизировать

$("input").on('input', function () {
  if($('datalist').find('option[value="'+this.value+'"]')){
    //your code as per need
    alert(this.value);
  }
});

Это может быть только Chrome, нигде еще не проверенный!, но я вижу changeсобытие запускается при выборе опции. Обычно changeпроисходит только в текстовых полях, когда поле теряет фокус. В change событие срабатывает до blur событие ЕСЛИ это обычное изменение, не связанное с данными, поэтому мы должны проверить оба: мы ищем changeза этим не сразу следует blur:

var timer;
el.addEventListener('change', function(e) {
    timer = setTimeout(function() {
        el.dispatchEvent(new CustomEvent('datalistchange'));
    }, 1);
});
el.addEventListener('blur', function(e) {
    clearTimeout(timer);
});

А затем вы можете слушать обычай datalistchangeсобытие вроде нормально. Или вы можете просто поместить свою конкретную логику вместо dispatchEvent.

jsFiddle здесь

      jQuery('input').on('input', function () {
  if($('datalist[id="' + jQuery(this).attr('list') + '"]').find('option[value="'+this.value+'"]')){
    //your code as per need
    alert(this.value);
  }
});

поэтому он найдет список данных, связанный с вводом

8 лет, и до сих пор нет хорошего ответа

Простой трюк с суффиксом пробела сделает то, что вам нужно, добавьте   в конце каждой опции, а затем обнаруживать (и удалять) ее в обработчике «ввода»

      <input list="my-options" id="my-input">
<datalist id="my-options">
  <option>Option 1 Here&nbsp;</option>
  <option>Option 2 Here&nbsp;</option>
</datalist>

<script>
$('#my-input').on('input',function (e)
{
        var v=$(e.target).val();
        if (v.slice(-1)=='\xa0')
        {
                $(e.target).val(v=v.slice(0,-1));
                console.log("option selected '"+v+"'");
        };
});
 
</script>
Другие вопросы по тегам