Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting hidden datalist option values

Tags:

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>
like image 333
Rick Viscomi Avatar asked Aug 22 '16 18:08

Rick Viscomi


2 Answers

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

like image 100
HybrisHelp Avatar answered Sep 20 '22 15:09

HybrisHelp


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.

const des = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value'); Object.defineProperty(HTMLInputElement.prototype, 'value', {   get: function() {     const value = des.get.call(this);        if (this.type === 'text' && this.list) {       const opt = [].find.call(this.list.options, o => o.value === value);       return opt ? opt.dataset.value : value;     }      return 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:

document.querySelector('input').addEventListener('input', event => {   const value = event.target.value;   const opt = [].find.call(event.target.list.options, o => o.value === value);    if (opt) {     event.target.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.

like image 22
Oriol Avatar answered Sep 17 '22 15:09

Oriol