如何制作自动完成输入字段下拉列表

How to make an autocomplete input field dropdown

我有一个输入字段,当用户点击它并开始输入时,我需要一个下拉菜单来显示它显示所有以正在输入的内容开头的下拉选项。我已经拥有大部分功能,只是不知道如何让它过滤数组并仅显示相关选项。

    const ampInput = document.querySelector('.amp-input');
    
    const ampDropdown = document.querySelector('.amp-dropdown-container');
    const ampOptions = document.querySelectorAll('.amp-options');

    ampInput.addEventListener('click', () => {
      ampDropdown.classList.add('amp-dropdown-container--active')
    })

    ampInput.addEventListener('focusout', (event) => {
      ampDropdown.classList.remove('amp-dropdown-container--active')
    });

    ampInput.addEventListener('input', onInputChange)

    function onInputChange() {
      const value = ampInput.value.toLowerCase();

      const filteredOptions = [];

      ampOptions.forEach((option) => {
        if (option.innerHTML.substr(0, value.length) === value)
          filteredOptions.push(option);
      });
      // console.log(filteredNames)
    }
<form action="{{ routes.search_url }}" method="get" role="search" autocomplete="off">
          <ul>
            <li id="autocomplete-wrapper">
              <input 
                id="autocomplete-input"
                type="search" 
                placeholder="Amp Hours (aH)" 
                class="amp-input">
                <ul class="amp-dropdown-container">
                  <h5 class="volt-options-title">Top Searches</h5>
                  <li><div class="amp-options">1.3</div></li>
                  <li><div class="amp-options">2.2</div></li>
                  <li><div class="amp-options">3.4</div></li>
                  <li><div class="amp-options">4.5</div></li>
                  <li><div class="amp-options">5</div></li>
                  <li><div class="amp-options">7</div></li>
                  <li><div class="amp-options">8</div></li>
                  <li><div class="amp-options">8.5</div></li>
                  <li><div class="amp-options">9</div></li>
                  <li><div class="amp-options">10</div></li>
                  <li><div class="amp-options">12</div></li>
                  <li><div class="amp-options">14</div></li>
                  <li><div class="amp-options">18</div></li>
                  <li><div class="amp-options">20</div></li>
                  <li><div class="amp-options">22</div></li>
                  <li><div class="amp-options">26</div></li>
                  <li><div class="amp-options">32</div></li>
                  <li><div class="amp-options">33</div></li>
                  <li><div class="amp-options">35</div></li>
                  <li><div class="amp-options">50</div></li>
                  <li><div class="amp-options">55</div></li>
                  <li><div class="amp-options">70</div></li>
                  <li><div class="amp-options">75</div></li>
                  <li><div class="amp-options">100</div></li>
                  <li><div class="amp-options">110</div></li>
                  <li><div class="amp-options">120</div></li>
                  <li><div class="amp-options">155</div></li>
                  <li><div class="amp-options">170</div></li>
                  <li><div class="amp-options">200</div></li>
                  <li><div class="amp-options">220</div></li>
                  <li><div class="amp-options">250</div></li>
                  <li><div class="amp-options">270</div></li>
                  <li><div class="amp-options">300</div></li>
                  <li><div class="amp-options">325</div></li>
                  <li><div class="amp-options">330</div></li>
                  <li><div class="last-link">400</div></li>
                </ul>
            </li>
          </ul> 
        </form>

您可以将一个空的 datalist 元素关联到搜索输入(我将其添加到您的 html 代码的底部)。请注意添加到搜索输入的属性 list="suggestions",该属性指示它填充一个从数据列表中挑选元素的建议框。

然后,在搜索输入发生变化时,您可以将过滤后的结果动态存储为数据列表的 option 个元素,从而使搜索输入显示一个建议框。

//const voltInput = document.querySelector('.search-input');
const ampInput = document.querySelector('.amp-input');
const ampDropdown = document.querySelector('.amp-dropdown-container');
const ampOptions = document.querySelectorAll('.amp-options');
const suggestions = document.getElementById('suggestions');

ampInput.addEventListener('click', () => {
  ampDropdown.classList.add('amp-dropdown-container--active')
})

ampInput.addEventListener('focusout', (event) => {
  ampDropdown.classList.remove('amp-dropdown-container--active')
});

ampInput.addEventListener('input', onInputChange)

function onInputChange() {
  const value = ampInput.value.toLowerCase();
  const filteredOptions = [];
  suggestions.innerHTML = ''

  ampOptions.forEach((option) => {
    if (option.innerHTML.substr(0, value.length) === value) {
      suggestions.innerHTML += '<option value="' + option.innerHTML + '">'
      filteredOptions.push(option.innerHTML);
    }
  })

  console.log(filteredOptions)
}
<form action="{{ routes.search_url }}" method="get" role="search" autocomplete="off">
          <ul>
            <li id="autocomplete-wrapper">
              <input 
                id="autocomplete-input"
                type="search" 
                list="suggestions"
                placeholder="Amp Hours (aH)" 
                class="amp-input">
                <ul class="amp-dropdown-container">
                  <h5 class="volt-options-title">Top Searches</h5>
                  <li><div class="amp-options">1.3</div></li>
                  <li><div class="amp-options">2.2</div></li>
                  <li><div class="amp-options">3.4</div></li>
                  <li><div class="amp-options">4.5</div></li>
                  <li><div class="amp-options">5</div></li>
                  <li><div class="amp-options">7</div></li>
                  <li><div class="amp-options">8</div></li>
                  <li><div class="amp-options">8.5</div></li>
                  <li><div class="amp-options">9</div></li>
                  <li><div class="amp-options">10</div></li>
                  <li><div class="amp-options">12</div></li>
                  <li><div class="amp-options">14</div></li>
                  <li><div class="amp-options">18</div></li>
                  <li><div class="amp-options">20</div></li>
                  <li><div class="amp-options">22</div></li>
                  <li><div class="amp-options">26</div></li>
                  <li><div class="amp-options">32</div></li>
                  <li><div class="amp-options">33</div></li>
                  <li><div class="amp-options">35</div></li>
                  <li><div class="amp-options">50</div></li>
                  <li><div class="amp-options">55</div></li>
                  <li><div class="amp-options">70</div></li>
                  <li><div class="amp-options">75</div></li>
                  <li><div class="amp-options">100</div></li>
                  <li><div class="amp-options">110</div></li>
                  <li><div class="amp-options">120</div></li>
                  <li><div class="amp-options">155</div></li>
                  <li><div class="amp-options">170</div></li>
                  <li><div class="amp-options">200</div></li>
                  <li><div class="amp-options">220</div></li>
                  <li><div class="amp-options">250</div></li>
                  <li><div class="amp-options">270</div></li>
                  <li><div class="amp-options">300</div></li>
                  <li><div class="amp-options">325</div></li>
                  <li><div class="amp-options">330</div></li>
                  <li><div class="amp-options last-link">400</div></li>
                </ul>
            </li>
          </ul> 
        </form>
        
        
        <datalist id="suggestions"></datalist>

  • 编辑

此更新(根据 OP 的评论)直接在 <ul> 元素上处理过滤:

//const voltInput = document.querySelector('.search-input');
const ampInput = document.querySelector('.amp-input');
const ampDropdown = document.querySelector('.amp-dropdown-container');
const ampOptions = document.querySelectorAll('.amp-options');
const suggestions = document.getElementById('suggestions');

ampInput.addEventListener('click', () => {
  ampDropdown.classList.add('amp-dropdown-container--active')
})

ampInput.addEventListener('focusout', (event) => {
  ampDropdown.classList.remove('amp-dropdown-container--active')
});

ampInput.addEventListener('input', onInputChange)

function onInputChange() {
  const value = ampInput.value.toLowerCase();
  const filteredOptions = [];

  ampOptions.forEach((option) => {
    if (option.innerHTML.substr(0, value.length) === value) {
      option.parentElement.classList.remove('hidden')
    } else {
      option.parentElement.classList.add('hidden')
    }
  })
}
.hidden {
  display: none;
}
<form action="{{ routes.search_url }}" method="get" role="search" autocomplete="off">
          <ul>
            <li id="autocomplete-wrapper">
              <input 
                id="autocomplete-input"
                type="search" 
                placeholder="Amp Hours (aH)" 
                class="amp-input">
                <ul class="amp-dropdown-container">
                  <h5 class="volt-options-title">Top Searches</h5>
                  <li><div class="amp-options">1.3</div></li>
                  <li><div class="amp-options">2.2</div></li>
                  <li><div class="amp-options">3.4</div></li>
                  <li><div class="amp-options">4.5</div></li>
                  <li><div class="amp-options">5</div></li>
                  <li><div class="amp-options">7</div></li>
                  <li><div class="amp-options">8</div></li>
                  <li><div class="amp-options">8.5</div></li>
                  <li><div class="amp-options">9</div></li>
                  <li><div class="amp-options">10</div></li>
                  <li><div class="amp-options">12</div></li>
                  <li><div class="amp-options">14</div></li>
                  <li><div class="amp-options">18</div></li>
                  <li><div class="amp-options">20</div></li>
                  <li><div class="amp-options">22</div></li>
                  <li><div class="amp-options">26</div></li>
                  <li><div class="amp-options">32</div></li>
                  <li><div class="amp-options">33</div></li>
                  <li><div class="amp-options">35</div></li>
                  <li><div class="amp-options">50</div></li>
                  <li><div class="amp-options">55</div></li>
                  <li><div class="amp-options">70</div></li>
                  <li><div class="amp-options">75</div></li>
                  <li><div class="amp-options">100</div></li>
                  <li><div class="amp-options">110</div></li>
                  <li><div class="amp-options">120</div></li>
                  <li><div class="amp-options">155</div></li>
                  <li><div class="amp-options">170</div></li>
                  <li><div class="amp-options">200</div></li>
                  <li><div class="amp-options">220</div></li>
                  <li><div class="amp-options">250</div></li>
                  <li><div class="amp-options">270</div></li>
                  <li><div class="amp-options">300</div></li>
                  <li><div class="amp-options">325</div></li>
                  <li><div class="amp-options">330</div></li>
                  <li><div class="amp-options last-link">400</div></li>
                </ul>
            </li>
          </ul> 
        </form>