代码之家  ›  专栏  ›  技术社区  ›  Leff

使用select作为自动完成输入的web材料设计

  •  0
  • Leff  · 技术社区  · 4 年前

    我在用谷歌的 material design for web . 我想用他们的 select component 作为自动完成组件。我的目标是 autocomplete 你可以在react mui中看到。我已经把 disabled readonly

    <div class="mdc-select demo-width-class">
      <div class="mdc-select__anchor">
        <span class="mdc-select__ripple"></span>
        <input type="text" class="mdc-select__selected-text">
        <i class="mdc-select__dropdown-icon"></i>
        <span class="mdc-floating-label">Pick a Food Group</span>
        <span class="mdc-line-ripple"></span>
      </div>
    
      <div class="mdc-select__menu mdc-menu mdc-menu-surface mdc-menu-surface--fullwidth">
        <ul class="mdc-list">
          <li class="mdc-list-item mdc-list-item--selected" data-value="" aria-selected="true"></li>
          <li class="mdc-list-item" data-value="grains">
            <span class="mdc-list-item__text">
              Bread, Cereal, Rice, and Pasta
            </span>
          </li>
          <li class="mdc-list-item" data-value="vegetables">
            <span class="mdc-list-item__text">
              Vegetables
            </span>
          </li>
          <li class="mdc-list-item" data-value="fruit">
            <span class="mdc-list-item__text">
              Fruit
            </span>
          </li>
        </ul>
      </div>
    </div>
    

    0 回复  |  直到 4 年前
        1
  •  1
  •   Community Neeleshkumar S    4 年前

    因为您已经提到,您希望在不使用react的情况下看到答案,因此在纯javascript中。我已经设法做到了。我结合了css和来自 @Sifat Haque w3schools . 虽然这看起来很简单,但要做到这一点却相当麻烦。

    const select = new mdc.select.MDCSelect(document.querySelector('.mdc-select'));
    
    function autocomplete(inp, arr) {
       var currentFocus;
     
      inp.addEventListener("input", autocomp);
      inp.addEventListener("click", autocomp);
    
      inp.addEventListener("focus", autocomp);
    
      function autocomp(e) {
        var a, b, i, val = this.value;
        closeAllLists();
        currentFocus = -1;
    
        a = document.createElement("ul");
        a.setAttribute("id", this.id + "autocomplete-list");
        a.setAttribute("class", "autocomplete-items mdc-list");
    
        document.getElementById("autocomp").appendChild(a);
    
        for (i = 0; i < arr.length; i++) {
          if (arr[i].substr(0, val.length).toUpperCase() == val.toUpperCase() || (val.trim()).length == 0) {
            b = document.createElement("li");
            b.setAttribute("class", "mdc-list-item")
            b.innerHTML = "<span class='mdc-list-item__text'>" + arr[i] + "</span>";
            b.innerHTML += "<input type='hidden' value='" + arr[i] + "'>";
    
            b.addEventListener("click", function(e) {
              inp.value = this.getElementsByTagName("input")[0].value;
              closeAllLists();
            });
            a.appendChild(b);
          }
        }
      }
      inp.addEventListener("keydown", function(e) {
        var x = document.getElementById(this.id + "autocomplete-list");
        if (x) x = x.getElementsByTagName("li");
        if (e.keyCode == 40) {
          currentFocus++;
          addActive(x);
        } else if (e.keyCode == 38) { //up
          currentFocus--;
          addActive(x);
        } else if (e.keyCode == 13) {
          e.preventDefault();
          if (currentFocus > -1) {
            if (x) x[currentFocus].click();
          }
        }
      });
    
      function addActive(x) {
        if (!x) return false;
        removeActive(x);
        if (currentFocus >= x.length) currentFocus = 0;
        if (currentFocus < 0) currentFocus = (x.length - 1);
        x[currentFocus].classList.add("autocomplete-active");
        x[currentFocus].classList.add("mdc-list-item--selected");
      }
    
      function removeActive(x) {
        for (var i = 0; i < x.length; i++) {
          x[i].classList.remove("autocomplete-active");
          x[i].classList.remove("mdc-list-item--selected");
        }
      }
    
      function closeAllLists(elmnt) {
        var x = document.getElementsByClassName("autocomplete-items");
        for (var i = 0; i < x.length; i++) {
          if (elmnt != x[i] && elmnt != inp) {
            x[i].parentNode.removeChild(x[i]);
          }
        }
      }
    
    }
    
    /*An array containing all the foods :*/
    var foods = ["fruit", "vegetables", "grains", "fries"];
    
    /*initiate the autocomplete function on the "myInput" element, and pass along the foods array as possible autocomplete values:*/
    autocomplete(document.getElementById("name-input"), foods);
    
    function makeActive(element) {
      document.getElementById("name-input").focus();
      element.classList.add("mdc-select--focused");
      element.classList.add("mdc-select--activated")
    }
    * {
      box-sizing: border-box;
    }
    
    .autocomplete {
      position: relative;
      display: inline-block;
    }
    
    input {
      border: 1px solid transparent;
      background-color: #f1f1f1;
      padding: 10px;
      font-size: 16px;
    }
    
    input[type=text] {
      background-color: transparent;
      width: 100%;
      margin-left: -200px;
      margin-top: 30px;
      z-index: -2;
    }
    
    input[type=text]:active {
      border: none;
    }
    
    .autocomplete-items {
      position: absolute;
      border: 1px solid #d4d4d4;
      border-bottom: none;
      border-top: none;
      z-index: 99;
      /*position the autocomplete items to be the same width as the container:*/
      top: 100%;
      left: 0;
      right: 0;
      max-height: 200px;
      /*overflow-y: scroll; */
    }
    
    .autocomplete-items li {
      padding: 10px;
      cursor: pointer;
      background-color: #fff;
      border-bottom: 1px solid #d4d4d4;
    }
    
    .mdc-select__menu {
      margin-top: -30px;
      z-index: 1;
      height: 150px;
      box-shadow: none;
      background-color: transparent;
      overflow-x: hidden !important;
    }
    <!DOCTYPE html>
    <html>
    
    <head>
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <!DOCTYPE html>
      <html>
    
      <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width">
        <link href="https://unpkg.com/material-components-web@v4.0.0/dist/material-components-web.min.css" rel="stylesheet">
        <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
    
        <script src="https://unpkg.com/material-components-web@v4.0.0/dist/material-components-web.min.js"></script>
    
      </head>
    
      <body>
    
    
        <h2>Autocomplete</h2>
    
        <p>Start typing:</p>
    
        <!--Make sure the form has the autocomplete function switched off:-->
    
        <form autocomplete="off" action="" method="post">
    
          <div class="mdc-select" onclick="makeActive(this)">
            <div class="mdc-select__anchor demo-width-class">
              <i class="mdc-select__dropdown-icon"></i>
              <div class="mdc-select__selected-text"></div>
              <span class="mdc-floating-label">Pick a Food Group</span>
              <div class="mdc-line-ripple"></div>
              <input type="text" id="name-input" name="selectione">
    
    
            </div>
            <div class="mdc-select__menu mdc-menu mdc-menu-surface">
              <div class="autocomplete" id='autocomp' style="width:200px;">
              </div>
            </div>
          </div>
    
          <input type="submit">
        </form>

        2
  •  0
  •   Sifat Haque    4 年前

    您需要将输入字段与select结合起来以获得一个输入字段,然后编写一些javascript来获得自动完成功能。你可以看看我的解决方案。

    console.clear();
    const select = new mdc.select.MDCSelect(document.querySelector('.mdc-select'));
    
    select.listen('MDCSelect:change', () => {
      alert(`Selected option at index ${select.selectedIndex} with value "${select.value}"`);
    });
    <!DOCTYPE html>
    <html>
    <head>
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width">
      <title>JS Bin</title>
      <link href="https://unpkg.com/material-components-web@v4.0.0/dist/material-components-web.min.css" rel="stylesheet">
      <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
      <script src="https://unpkg.com/material-components-web@v4.0.0/dist/material-components-web.min.js"></script>
    </head>
    <body>
      <div class="mdc-select">
      <div class="mdc-select__anchor demo-width-class">
        <i class="mdc-select__dropdown-icon"></i>
        <div class="mdc-select__selected-text"></div>
        <span class="mdc-floating-label">Pick a Food Group</span>
        <div class="mdc-line-ripple"></div>
      </div>
    
      <div class="mdc-select__menu mdc-menu mdc-menu-surface demo-width-class">
        <ul class="mdc-list">
          <input type="text" class="mdc-list-item--selected mdc-text-field__input" id="name-input">
          <label for="name-input" class="mdc-floating-label">search....</label>
          <li class="mdc-list-item" data-value="grains">
            Bread, Cereal, Rice, and Pasta
          </li>
          <li class="mdc-list-item" data-value="vegetables">
            Vegetables
          </li>
          <li class="mdc-list-item" data-value="fruit">
            Fruit
          </li>
          
          <input type="hidden" name="input_name" value="input_value" class="my_mdc-select__value" />
        
        </ul>
      </div>
    </div>
    
    
      
    
    
    </body>
    </html>
        3
  •  0
  •   sauhardnc Ijaz Ahmed Bhatti    4 年前

    我已经创建了一个演示,它在某种程度上满足了您的需要。它有两个问题-

    1. 用户必须单击两次(双击)才能输入值(我不能让它在一次单击中工作)
    2. label

    如果有人知道如何解决这些问题,他们的想法是 欢迎光临。
    你解决了吗?如果是的话,请这样做,也请启发我们(我)。

    也, jquery 在本守则中 vanilla javascript HTML 这应该得到解决。

    // initialize
    const select = new mdc.select.MDCSelect(document.querySelector('.mdc-select'));
    
    // stop the original propagation so that input field remains editable
    $('#food').on('click', (event) => {
      return false;
    });
    
    // Demo Data
    const foodArr = ['Bread, Cereal, Rice, and Pasta', 'Vegetables', 'Fruit'];
    
    // You'll have to use ajax here to get the data
    $('#food').on('keyup', (event) => {
    
      //console.clear();
      let $this = $(event.currentTarget);
      let currValue = $this.val();
    
      let search = new RegExp(currValue, 'i'); // prepare a regex object // Your custom condition
    
      let matchArr = foodArr.filter(item => search.test(item)); //store the result in an array
      let $select = "";
    
      // check if array is empty
      if (matchArr.length > 0) {
    
        // map the elements of the array and create option html
        matchArr.forEach((item) => {
    
          $select += `<li class="mdc-list-item" data-value="${item}"> ${item}</li>`;
    
        })
    
      } else { // if array is empty, display no match
    
        $select += `<li class="mdc-list-item" id="no_match"> No match found!</li>`;
    
      }
      //console.log(matchArr);
    
      // if the data was selected before, unselect it
      $('.mdc-list-item--selected:first').attr({'data-value': ''});
      $('.mdc-list-item--selected:first').text('');
      $('.mdc-list-item--selected:not(:first)').removeClass('mdc-list-item--selected');
    
      // remove all previous option elements
      $('.mdc-list-item:not(.mdc-list-item--selected:first)').remove();
    
      // add new option elements
      $('.mdc-list-item--selected').after($select);
    
      // start the click function, so that dropdown doesn't close
      $this.click();
    });
    
    // When any option is selected, show it on input field
    $(document).on('click', '.mdc-list-item:not(#no_match)', (event) => {
      
      let $this = $(event.currentTarget);
      $this.addClass('mdc-list-item--selected');
      
      $('.mdc-floating-label').addClass('mdc-floating-label--float-above');
      
      $('.mdc-select__anchor').addClass('demo-width-class mdc-ripple-upgraded')
      $('.mdc-line-ripple').addClass('mdc-line-ripple--active mdc-line-ripple--deactivating')
      $('.mdc-line-ripple').css({'transform-origin': '182px center'})
      
      $('#food').val($this.attr('data-value'));
      // return false;
      // event.stopImmediatePropagation()
    });
    
    // if clicked on no match, value of input field should be empty, alternatively you can also make option disabled
    $(document).on('click', '#no_match', (event) => {
      
      $('#food').val('');
      
    });
    <!DOCTYPE html>
    <html>
    <head>
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width">
      <title>@sauhardnc</title>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
      <link href="https://unpkg.com/material-components-web@v4.0.0/dist/material-components-web.min.css" rel="stylesheet">
      <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
      <script src="https://unpkg.com/material-components-web@v4.0.0/dist/material-components-web.min.js"></script>
    </head>
    
    <body>
      <div class="mdc-select">
        <div class="mdc-select__anchor demo-width-class" style="width: 100%">
          <i class="mdc-select__dropdown-icon"></i>
          <input type="text" class="mdc-select__selected-text" id="food"></input>
          <!-- Give a unique id -->
          <!--<div contenteditable="true" class="mdc-select__selected-text" id="fruit"></div>-->
          <span class="mdc-floating-label">Pick a Food Group</span>
          <div class="mdc-line-ripple"></div>
        </div>
    
        <div class="mdc-select__menu mdc-menu mdc-menu-surface demo-width-class" style="width: 100%">
          <ul class="mdc-list">
            <li class="mdc-list-item mdc-list-item--selected" data-value="" aria-selected="true"></li>
            <li class="mdc-list-item" data-value="Bread, Cereal, Rice, and Pasta">
              Bread, Cereal, Rice, and Pasta
            </li>
            <li class="mdc-list-item" data-value="Vegetables">
              Vegetables
            </li>
            <li class="mdc-list-item" data-value="Fruit">
              Fruit
            </li>
          </ul>
        </div>
      </div>
    </body>
    
    </html>
        4
  •  0
  •   Nithish    4 年前

    这是我能做到的,希望对你的实现有所帮助。我还没有完全实现过滤逻辑和所有,但能够输入和显示下拉同时。

    const menuElement = document.querySelector(".mdc-menu");
    // const menu = new mdc.menu.MDCMenu(menuElement);
    
    const inputLabel = document.querySelector(".mdc-text-field");
    const inputElem = inputLabel.querySelector("input");
    const dropdownIcon = document.querySelector(".mdc-select__dropdown-icon");
    let isMenuOpen = false;
    
    inputLabel.addEventListener("click", () => {
      inputElem.focus();
      // menu.open = true;
      if (!isMenuOpen) {
        menuElement.classList.remove("list-menu-close");
        menuElement.classList.add("list-menu-open");
        dropdownIcon.classList.add("dropdown-icon-up");
      } else {
        menuElement.classList.remove("list-menu-open");
        menuElement.classList.add("list-menu-close");
        dropdownIcon.classList.remove("dropdown-icon-up");
      }
      isMenuOpen = !isMenuOpen;
    });
    
    inputElem.addEventListener("blur", () => {
      menuElement.classList.remove("list-menu-open");
      menuElement.classList.add("list-menu-close");
      dropdownIcon.classList.remove("dropdown-icon-up");
      isMenuOpen = false;
    });
    
    
        <div class="dropdown-container">
          <label class="mdc-text-field mdc-text-field--filled">
            <span class="mdc-text-field__ripple"></span>
            <input
              class="mdc-text-field__input"
              type="text"
              aria-labelledby="my-label-id"
            />
            <i class="mdc-select__dropdown-icon"></i>
          </label>
          <div>
            <div class="mdc-menu mdc-menu-surface list-menu">
              <ul
                class="mdc-list"
                role="menu"
                aria-hidden="true"
                aria-orientation="vertical"
                tabindex="-1"
              >
                <li class="mdc-list-item" role="menuitem">
                  <span class="mdc-list-item__text">A Menu Item</span>
                </li>
                <li class="mdc-list-item" role="menuitem">
                  <span class="mdc-list-item__text">Another Menu Item</span>
                </li>
              </ul>
            </div>
          </div>
        </div>
    
    .dropdown-container {
      position: relative;
    }
    
    .list-menu {
      position: absolute;
      top: 60px;
    }
    
    .list-menu-open {
      display: block;
      opacity: 1;
    }
    
    .list-menu-close {
      display: none;
      opacity: 0;
    }
    
    .dropdown-icon-up {
      transform: rotate(180deg) translateY(-5px);
    }