151

I would like to have an input field that users can enter custom text value or choose from drop down. A regular <select> only offers drop down options.

How can I make a <select> accept custom value? For instance: Ford?

<select>
  <option value="volvo">Volvo</option>
  <option value="saab">Saab</option>
  <option value="mercedes">Mercedes</option>
  <option value="audi">Audi</option>
</select>
Robotnik
  • 3,643
  • 3
  • 31
  • 49
Ib33X
  • 6,764
  • 4
  • 28
  • 30
  • You could use javascript to dynamically add an option to the select but then using this information would become a real pain. – David Apr 13 '11 at 14:11
  • I did not add that option for custom values on my website https://www.finnmglas.com/contact/ however someone contacted me with a custom value. That is so weird – finnmglas May 13 '20 at 06:36

8 Answers8

351

HTML5 has a built-in combo box. You create a text input and a datalist. Then you add a list attribute to the input, with a value of the id of the datalist.

Update: As of March 2019 all major browsers (now including Safari 12.1 and iOS Safari 12.3) support datalist to the level needed for this functionality. See caniuse for detailed browser support.

It looks like this:

<input type="text" list="cars" />
<datalist id="cars">
  <option>Volvo</option>
  <option>Saab</option>
  <option>Mercedes</option>
  <option>Audi</option>
</datalist>
Robotnik
  • 3,643
  • 3
  • 31
  • 49
Dmitry
  • 6,716
  • 14
  • 37
  • 39
  • 3
    It works for me well. In many cases we don't need to support old browsers. I only added "down arrow" image on the background of input field to give users a hint it's expandable. Code (you need an actual image file): `` – Eugene Kardash Nov 01 '16 at 20:43
  • 5
    I just tested in recent versions of IE, Firefox and Chrome with all working fine. I think this is a great simple solution to this common problem for many cases. – kerl Jan 19 '17 at 19:55
  • 5
    I really wanted to use this but I needed to set a default value. The user only sees the default in the drop down vs. all the options (because they are filtered out). They would need to know to clear the input field before seeing all the options. – Justin Jul 17 '18 at 11:06
  • In Chrome this worked great with a short list. But once I added nearly 40 options, Chrome would no longer display the full list on the screen. Also if I added a value to the option tag `` Chrome displayed that value to the left, and then the other data to the right. Really bizarre. – Joe Jan 09 '20 at 19:36
  • Found a page worth linking to this page. https://stackoverflow.com/q/48338606/2943403 – mickmackusa Jun 05 '20 at 06:37
  • 5
    The major cons of this method is, if I already selected Volvo then it won't display other options until we clear the whole text. This is not the case while using `. – Srk95 Oct 14 '20 at 09:47
  • 1
    Is there a way to make the dropdown menu appear with 1 click instead of 2? – default123 Dec 03 '20 at 14:10
  • Agreed with Srk95. It's a shame it doesn't show the full list after an option is selected. Not sure who thought this was a good idea. Awful design. – train Mar 11 '22 at 18:59
28

Alen Saqe's latest JSFiddle didn't toggle for me on Firefox, so I thought I would provide a simple html/javascript workaround that will function nicely within forms (regarding submission) until the day that the datalist tag is accepted by all browsers/devices. For more details and see it in action, go to: http://jsfiddle.net/6nq7w/4/ Note: Do not allow any spaces between toggling siblings!

<!DOCTYPE html>
<html>
<script>
function toggleField(hideObj,showObj){
  hideObj.disabled=true;        
  hideObj.style.display='none';
  showObj.disabled=false;   
  showObj.style.display='inline';
  showObj.focus();
}
</script>
<body>
<form name="BrowserSurvey" action="#">
Browser: <select name="browser" 
          onchange="if(this.options[this.selectedIndex].value=='customOption'){
              toggleField(this,this.nextSibling);
              this.selectedIndex='0';
          }">
            <option></option>
            <option value="customOption">[type a custom value]</option>
            <option>Chrome</option>
            <option>Firefox</option>
            <option>Internet Explorer</option>
            <option>Opera</option>
            <option>Safari</option>
        </select><input name="browser" style="display:none;" disabled="disabled" 
            onblur="if(this.value==''){toggleField(this,this.previousSibling);}">
<input type="submit" value="Submit">
</form>
</body>
</html>

mickmackusa
  • 43,625
  • 12
  • 83
  • 136
  • I would like to go throught that fidle again! Witch version of Firefox was not supported there! I tested it with some version i dont remember! Kudos! – Alen Saqe Nov 14 '14 at 12:48
  • I dont' know which version of FF I was on. I just had a look on FF34.0 and I am getting functionality now, so no worries. However, the default toggling option "Other" can be cleared away. When I remove "Other" by editing the value, the dropmenu doesn't offer an intuitive value to select (to access the editing feature). I think this comes down to personal preference. Because the dropmenu arrow is still present when the field is editable, users may not realize the field is editable. Not having a dig at you; just some feedback. My snippet also considers field naming inside of a
    .
    – mickmackusa Dec 08 '14 at 05:13
  • The end result of this ingenious but indecipherable (to me) script+html is to attach the selected option value, or entered text, to a GET of the same page as a query string. Does anyone know how to convert the action to a POST, so I can grab the value in a php file and do something with it there? – Han Sep 29 '19 at 08:17
  • I composed this script with the specific intention for it to behave in accordance with html form submissions. Are you using the post method as an attribute in the form tag? @Han if you create a 3v4l.org link of your isolated snippet, I can take a quick look and possibly advise. – mickmackusa Sep 29 '19 at 09:04
  • 1
    Boy do I feel dumb. I forgot to put a method in the form tag. It worked as posted with this very slight modification:
    ...Beautiful script, mickmackusa. Thanks for your followup hint!
    – Han Sep 29 '19 at 17:54
16

jQuery Solution!

Demo: http://jsfiddle.net/69wP6/2/

Another Demo Below(updated!)

I needed something similar in a case when i had some fixed Options and i wanted one other option to be editable! In this case i made a hidden input that would overlap the select option and would be editable and used jQuery to make it all work seamlessly.

I am sharing the fiddle with all of you!

HTML

<div id="billdesc">
    <select id="test">
      <option class="non" value="option1">Option1</option>
      <option class="non" value="option2">Option2</option>
      <option class="editable" value="other">Other</option>
    </select>
    <input class="editOption" style="display:none;"></input>
</div>

CSS

body{
    background: blue;
}
#billdesc{
    padding-top: 50px;
}
#test{
    width: 100%;
    height: 30px;
}
option {
    height: 30px;
    line-height: 30px;
}

.editOption{
    width: 90%;
    height: 24px;
    position: relative;
    top: -30px

}

jQuery

var initialText = $('.editable').val();
$('.editOption').val(initialText);

$('#test').change(function(){
var selected = $('option:selected', this).attr('class');
var optionText = $('.editable').text();

if(selected == "editable"){
  $('.editOption').show();


  $('.editOption').keyup(function(){
      var editText = $('.editOption').val();
      $('.editable').val(editText);
      $('.editable').html(editText);
  });

}else{
  $('.editOption').hide();
}
});

Edit : Added some simple touches design wise, so people can clearly see where the input ends!

JS Fiddle : http://jsfiddle.net/69wP6/4/

Alen Saqe
  • 479
  • 7
  • 25
16

If the datalist option doesn't fulfill your requirements, take a look to the Select2 library and the "Dynamic option creation"

$(".js-example-tags").select2({
  tags: true
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/css/select2.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/js/select2.min.js"></script>


<select class="form-control js-example-tags">
  <option selected="selected">orange</option>
  <option>white</option>
  <option>purple</option>
</select>
Sogeking
  • 780
  • 8
  • 19
10

You can't really. You'll have to have both the drop down, and the text box, and have them pick or fill in the form. Without javascript you could create a separate radio button set where they choose dropdown or text input, but this seems messy to me. With some javascript you could toggle disable one or the other depending on which one they choose, for instance, have an 'other' option in the dropdown that triggers the text field.

Sam
  • 1,233
  • 1
  • 9
  • 16
2

Using one of the above solutions ( @mickmackusa ), I made a working prototype in React 16.8+ using Hooks.

https://codesandbox.io/s/heuristic-dewdney-0h2y2

I hope it helps someone.

dano
  • 5,640
  • 5
  • 27
  • 27
  • I am honored. I just checked my records and this was the 12th post that I made here on Stack Overflow -- feels like a million years ago. – mickmackusa Sep 29 '19 at 10:00
  • I just had a play with your demo link and it looks like you have lost the effect to indefinitely toggle between the two types of fields. – mickmackusa Sep 25 '20 at 20:44
  • this answer is too reliant on the off-site link. Please [edit] your answer to include the actual code. – mickmackusa Nov 03 '22 at 06:48
2

This is the same solution as @mickmackusa but written using jquery:

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form name="BrowserSurvey" action="#">
  Browser: <select name="browser" onchange="if($(this).val()=='customOption'){$(this).hide().prop('disabled',true);$('input[name=browser]').show().prop('disabled', false).focus();$(this).val(null);}">
    <option></option>
    <option value="customOption">[type a custom value]</option>
    <option>Chrome</option>
    <option>Firefox</option>
    <option>Internet Explorer</option>
    <option>Opera</option>
    <option>Safari</option></select><input name="browser" style="display:none;" disabled="disabled" onblur="if($(this).val()==''){$(this).hide().prop('disabled',true);$('select[name=browser]').show().prop('disabled', false).focus();}">
  <input type="submit" value="Submit">
</form>

Maybe a more readable version:

function toggle($toBeHidden, $toBeShown) {
  $toBeHidden.hide().prop('disabled', true);
  $toBeShown.show().prop('disabled', false).focus();
}

function showOptions(inputName) {
  var $select = $(`select[name=${inputName}]`);
  toggle($(`input[name=${inputName}]`), $select);
  $select.val(null);
}


function showCustomInput(inputName) {
  toggle($(`select[name=${inputName}]`), $(`input[name=${inputName}]`));
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form name="BrowserSurvey" action="#">
Browser: <select name="browser" onchange="if($(this).val()=='customOption')showCustomInput('browser')">
    <option></option>
    <option value="customOption">[type a custom value]</option>
    <option>Chrome</option>
    <option>Firefox</option>
    <option>Internet Explorer</option>
    <option>Opera</option>
    <option>Safari</option></select><input name="browser" style="display:none;" disabled="disabled" onblur="if($(this).val()=='')showOptions('browser')">
<input type="submit" value="Submit">
</form>
adnanmuttaleb
  • 3,388
  • 1
  • 29
  • 46
0
<input type="text" list="cars" />
<datalist id="cars">
  <option>Volvo</option>
  <option>Saab</option>
  <option>Mercedes</option>
  <option>Audi</option>
</datalist>
  • Your answer could be improved with additional supporting information. Please [edit] to add further details about your code. – CreepyRaccoon May 05 '23 at 15:27