Setting hidden datalist option values

我与影子孤独终老i 提交于 2020-01-29 10:30:15

问题


In the snippet below, I have two methods to choose an item: input with datalist and traditional select with options.

The select element keeps the option values hidden, and we're still able to get it with this.value. However, with the datalist, the value is actually displayed and the text content of the option is displayed as a secondary label.

What I'd like is to have the input+datalist approach behave like a traditional select, where "Foo" and "Bar" are shown as options that when selected have values of "1" and "2" respectively.

I've also added a repeated name "Foo" with value "3". This is to show that any solution must not depend on unique options.

<input list="options" onchange="console.log(this.value)"/>
<datalist id="options">
  <option value="1">Foo</option>
  <option value="2">Bar</option>
  <option value="3">Foo</option>
</datalist>

<select onchange="console.log(this.value)">
  <option value=""></option>
  <option value="1">Foo</option>
  <option value="2">Bar</option>
  <option value="3">Foo</option>
</select>

回答1:


There is no native way. For text inputs

The input element represents a one line plain text edit control for the element's value.

So it's not possible to make a text input display some text different than its value.

You could hijack the value getter in HTMLInputElement.prototype, but I don't recommend it, and I don't see any way to know which option was chosen if the values are not unique.

var des = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value');
Object.defineProperty(HTMLInputElement.prototype, 'value', { get: function() {
  if(this.type === 'text' && this.list) {
    var value = des.get.call(this);
    var opt = [].find.call(this.list.options, function(option) {
      return option.value === value;
    });
    return opt ? opt.dataset.value : value;
  }
}});
<input list="options" oninput="console.log(this.value);" />
<datalist id="options">
  <option data-value="1">Foo</option>
  <option data-value="2">Bar</option>
  <option data-value="3">Foo</option>
</datalist>

Or maybe you can let the input show the value of the option instead of the text, but replace it immediately:

var inp = document.querySelector('input');
inp.addEventListener('input', function() {
  var value = this.value;
  var opt = [].find.call(this.list.options, function(option) {
    return option.value === value;
  });
  if(opt) {
    this.value = opt.textContent;
  }
});
<input list="options" oninput="console.log(this.value);" />
<datalist id="options">
  <option value="1">Foo</option>
  <option value="2">Bar</option>
  <option value="3">Foo</option>
</datalist>

In the second example, oninput="console.log(this.value)" shows the value of the option because that code runs before replacing the value to the text content. If you want later .value accessions to return the option value, you will need to hijack the value getter like in the first example.




回答2:


You can use data-value and jquery to make your value hidden.

e.g:

$(document).ready(function() {

    $('#submit').click(function()
    {
        var value = $('#selected').val();
        alert($('#browsers [value="' + value + '"]').data('value'));
    });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<input id="selected" list="browsers" name="browser">
<datalist id="browsers">
    <option data-value="1" value="InternetExplorer"></option>
    <option data-value="2" value="Firefox"></option>
    <option data-value="3" value="Chrome"></option>

</datalist>
<input id="submit" type="submit">

jsfiddle

Thanks to @guest271314




回答3:


The correct syntax of datalist is like bellow. Also there is no point to have two options with the same name. I took the JavaScript out of the HTML as it should be. ID attribute of the individual options can be replaced with other attribute.

$(function() {
  $('input[name=chooseOption]').on('input',function() {
    var selectedOption = $('option[value="'+$(this).val()+'"]');
    console.log(selectedOption.length ? selectedOption.attr('id') : 'This opiton is not in the list!');
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<input list="options" name="chooseOption">
<datalist id="options">
  <option id="1" value="Foo">
  <option id="2" value="Bar">
  <option id="3" value="Foo">
</datalist>



回答4:


So for the codebase I'm working on, I have a programatic fieldWriter for writing dynamic forms. I was asked to turn a bunch of selects into autocomplete datalists. What I did for this is set up 3 elements.

  • One datalist with the name "somefield_dl"
  • One visible input with the name "somefield_proxy"
  • One hidden input with the name "somefield"

On the datalists, I set each option like <option data-value="439" value="Readable Text"></option>

With event handlers, anytime the "somefield_proxy" changes, the "somefield" is changed to the data-value of the option from "somefield_dl" with a matching value.

Code-wise, for using these, the main difference is that every time you update the field's value, you have to trigger the click event on the hidden input to update the proxy input. Also, when gathering data, you have to exclude the elements whose name ends with _proxy.




回答5:


Do not know this will help you, just made a try

  <input list="options" id="opt" oninput="onInput()">
  <datalist id="options">
        <option value="1">Foo</option>
       <option value="2">Bar</option>
       <option value="3">Foo</option> 
        <option value="4">Foo</option>
       <option value="5">Bar</option>
       <option value="6">Foo</option> 
  </datalist>




 $( document ).ready(function() {              
         var x =  document.getElementById("options");
           for (i = 0; i < x.length; i++)
            alert(x.options[i].value);     


            $("#opt").click(function(){
                 $("#opt").val("");});                   
             });

     function onInput() {
            var val = document.getElementById("opt").value;
            var opts = document.getElementById('options').childNodes;
             for (var i = 0; i < opts.length; i++) {
                    if (opts[i].value === val) {                
                    document.getElementById("opt").value = opts[i].value + "   "+ opts[i].innerHTML;
                    break;
                  }
                }
              }


来源:https://stackoverflow.com/questions/39086427/setting-hidden-datalist-option-values

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!