Editable 'Select' element

前端 未结 4 1213
佛祖请我去吃肉
佛祖请我去吃肉 2020-11-29 01:45

I would like to have a select element in the form but besides the options in the dropdown, it would be useful to be able to edit it and add new option but not with another i

相关标签:
4条回答
  • 2020-11-29 01:55

    Nothing is impossible. Here's a solution that simply sets the value of a text input whenever the value of the <select> changes (rendering has been tested on Firefox and Google Chrome):

    .select-editable {position:relative; background-color:white; border:solid grey 1px;  width:120px; height:18px;}
    .select-editable select {position:absolute; top:0px; left:0px; font-size:14px; border:none; width:120px; margin:0;}
    .select-editable input {position:absolute; top:0px; left:0px; width:100px; padding:1px; font-size:12px; border:none;}
    .select-editable select:focus, .select-editable input:focus {outline:none;}
    <div class="select-editable">
      <select onchange="this.nextElementSibling.value=this.value">
        <option value=""></option>
        <option value="115x175 mm">115x175 mm</option>
        <option value="120x160 mm">120x160 mm</option>
        <option value="120x287 mm">120x287 mm</option>
      </select>
      <input type="text" name="format" value=""/>
    </div>
    jsfiddle: https://jsfiddle.net/nwH8A/

    The next example adds the user input to the empty option slot of the <select> (thanks to @TomerPeled). It also has a little bit more flexible/variable CSS:

    .select-editable {position:relative; width:120px;}
    .select-editable > * {position:absolute; top:0; left:0; box-sizing:border-box; outline:none;}
    .select-editable select {width:100%;}
    .select-editable input {width:calc(100% - 20px); margin:1px; border:none; text-overflow:ellipsis;}
    <div class="select-editable">
      <select onchange="this.nextElementSibling.value=this.value">
        <option value=""></option>
        <option value="115x175 mm">115x175 mm</option>
        <option value="120x160 mm">120x160 mm</option>
        <option value="120x287 mm">120x287 mm</option>
      </select>
      <input type="text" oninput="this.previousElementSibling.options[0].value=this.value; this.previousElementSibling.options[0].innerHTML=this.value" onchange="this.previousElementSibling.selectedIndex=0" value="" />
    </div>
    jsfiddle: https://jsfiddle.net/pu7cndLv/1/


    DataList

    In HTML5 you can also do this with the <input> list attribute and <datalist> element:

    <input list="browsers" name="browser">
    <datalist id="browsers">
      <option value="Internet Explorer">
      <option value="Firefox">
      <option value="Chrome">
      <option value="Opera">
      <option value="Safari">
    </datalist>
    (click once to focus and edit, click again to see option dropdown)
    jsfiddle: https://jsfiddle.net/hrkxebtw/

    But this acts more like an auto-complete list; once you start typing, only the options that contain the typed string are left as suggestions. Depending on what you want to use it for, this may or may not be practical.

    0 讨论(0)
  • 2020-11-29 01:58

    Based on the other answers, here is a first draft for usage with knockout:

    Usage

          <div data-bind="editableSelect: {options: optionsObservable, value: nameObservable}"></div>
    

    Knockout data binding

    composition.addBindingHandler('editableSelect',
      {
        init: function(hostElement, valueAccessor) {
    
          var optionsObservable = getOptionsObservable();
          var valueObservable = getValueObservable();
    
          var $editableSelect = $(hostElement);
          $editableSelect.addClass('select-editable');
    
          var editableSelect = $editableSelect[0];
    
          var viewModel = new editableSelectViewModel(optionsObservable, valueObservable);
          ko.applyBindingsToNode(editableSelect, { compose: viewModel });
    
          //tell knockout to not apply bindings twice
          return { controlsDescendantBindings: true };
    
          function getOptionsObservable() {
            var accessor = valueAccessor();
            return getAttribute(accessor, 'options');
          }
    
          function getValueObservable() {
            var accessor = valueAccessor();
            return getAttribute(accessor, 'value');
          }
        }
      });
    

    View

    <select
      data-bind="options: options, event:{ focus: resetComboBoxValue, change: setTextFieldValue} "
      id="comboBox"
      ></select>
    <input
      data-bind="value: value, , event:{ focus: textFieldGotFocus, focusout: textFieldLostFocus}"
      id="textField"
      type="text"/>
    

    ViewModel

    define([
      'lodash',
      'services/errorHandler'
    ], function(
      _,
      errorhandler
    ) {
    
      var viewModel = function(optionsObservable, valueObservable) {
    
        var self = this;
        self.options = optionsObservable();
        self.value = valueObservable;
        self.resetComboBoxValue = resetComboBoxValue;
        self.setTextFieldValue = setTextFieldValue;
        self.textFieldGotFocus = textFieldGotFocus;
        self.textFieldLostFocus = textFieldLostFocus;
    
        function resetComboBoxValue() {
          $('#comboBox').val(null);
        }
    
        function setTextFieldValue() {
          var selection = $('#comboBox').val();
          self.value(selection);
        }
    
        function textFieldGotFocus() {
          $('#comboBox').addClass('select-editable-input-focus');
    
        }
    
        function textFieldLostFocus() {
          $('#comboBox').removeClass('select-editable-input-focus');
        }
    
      };
      errorhandler.includeIn(viewModel);
    
      return viewModel;
    });
    

    CSS

    .select-editable {
    
      display: block;
      width: 100%;
      height: 31px;
      padding: 6px 12px;
      font-size: 12px;
      line-height: 1.42857143;
      color: #555555;
      background-color: #ffffff;
      background-image: none;
      border: 1px solid #cccccc;
      border-radius: 0px;
      -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
      box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
      -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s;
      -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
      transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;padding: 0;
    }
    
    
    .select-editable select {
      outline:0;
      padding-left: 10px;
      border:none;
      width:100%;
      height: 29px;
    }
    
    
    .select-editable input {
      outline:0;
      position: relative;
      top: -27px;
      margin-left: 10px;
      width:90%;
      height: 25px;
      border:none;
    }
    
    .select-editable select:focus {
      outline:0;
      border: 1px solid #66afe9;
      -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
      box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
    }
    
    
    
    
    .select-editable input:focus {
      outline:0;
    }
    
    .select-editable-input-focus {
    outline:0;
      border: 1px solid #66afe9 !important;
      -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
      box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
    }
    
    0 讨论(0)
  • 2020-11-29 02:08

    A bit more universal <select name="env" style="width: 200px; position:absolute;" onchange="this.nextElementSibling.value=this.value">
        <option></option>
        <option>1</option>
        <option>2</option>
        <option>3</option> 
    </select>
    <input style="width: 178px; margin-top: 1px; border: none; position:relative; left:1px; margin-right: 25px;" value="123456789012345678901234"/>layout ...

    0 讨论(0)
  • 2020-11-29 02:12

    Similar to answer above but without the absolute positioning:

    <select style="width: 200px; float: left;" onchange="this.nextElementSibling.value=this.value">
        <option></option>
        <option>1</option>
        <option>2</option>
        <option>3</option> 
    </select>
    <input style="width: 185px; margin-left: -199px; margin-top: 1px; border: none; float: left;"/>
    

    So create a input box and put it over the top of the combobox

    0 讨论(0)
提交回复
热议问题