Home > Back-end >  How to make an autocomplete input field dropdown
How to make an autocomplete input field dropdown

Time:05-18

I have an input field which when a user clicks into it and begins typing, i need a dropdown to show up which displays all the dropdown options that begin with what is being typed. I have most of the functionality already I just cant figure out how to get it to filter through the array and display only the relevant options.

enter image description here

    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)" 
                >
                <ul >
                  <h5 >Top Searches</h5>
                  <li><div >1.3</div></li>
                  <li><div >2.2</div></li>
                  <li><div >3.4</div></li>
                  <li><div >4.5</div></li>
                  <li><div >5</div></li>
                  <li><div >7</div></li>
                  <li><div >8</div></li>
                  <li><div >8.5</div></li>
                  <li><div >9</div></li>
                  <li><div >10</div></li>
                  <li><div >12</div></li>
                  <li><div >14</div></li>
                  <li><div >18</div></li>
                  <li><div >20</div></li>
                  <li><div >22</div></li>
                  <li><div >26</div></li>
                  <li><div >32</div></li>
                  <li><div >33</div></li>
                  <li><div >35</div></li>
                  <li><div >50</div></li>
                  <li><div >55</div></li>
                  <li><div >70</div></li>
                  <li><div >75</div></li>
                  <li><div >100</div></li>
                  <li><div >110</div></li>
                  <li><div >120</div></li>
                  <li><div >155</div></li>
                  <li><div >170</div></li>
                  <li><div >200</div></li>
                  <li><div >220</div></li>
                  <li><div >250</div></li>
                  <li><div >270</div></li>
                  <li><div >300</div></li>
                  <li><div >325</div></li>
                  <li><div >330</div></li>
                  <li><div >400</div></li>
                </ul>
            </li>
          </ul> 
        </form>

CodePudding user response:

You can associate an empty datalist element to to the search input (I added it on bottom of your html code). Note the attribute list="suggestions" added to the search input, which instructs it to populate a suggestion box picking elements from the datalist.

Then, on search input change, you can store your filtered results dynamically as option elements of the datalist, making the search input show a suggestion box.

//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)" 
                >
                <ul >
                  <h5 >Top Searches</h5>
                  <li><div >1.3</div></li>
                  <li><div >2.2</div></li>
                  <li><div >3.4</div></li>
                  <li><div >4.5</div></li>
                  <li><div >5</div></li>
                  <li><div >7</div></li>
                  <li><div >8</div></li>
                  <li><div >8.5</div></li>
                  <li><div >9</div></li>
                  <li><div >10</div></li>
                  <li><div >12</div></li>
                  <li><div >14</div></li>
                  <li><div >18</div></li>
                  <li><div >20</div></li>
                  <li><div >22</div></li>
                  <li><div >26</div></li>
                  <li><div >32</div></li>
                  <li><div >33</div></li>
                  <li><div >35</div></li>
                  <li><div >50</div></li>
                  <li><div >55</div></li>
                  <li><div >70</div></li>
                  <li><div >75</div></li>
                  <li><div >100</div></li>
                  <li><div >110</div></li>
                  <li><div >120</div></li>
                  <li><div >155</div></li>
                  <li><div >170</div></li>
                  <li><div >200</div></li>
                  <li><div >220</div></li>
                  <li><div >250</div></li>
                  <li><div >270</div></li>
                  <li><div >300</div></li>
                  <li><div >325</div></li>
                  <li><div >330</div></li>
                  <li><div >400</div></li>
                </ul>
            </li>
          </ul> 
        </form>
        
        
        <datalist id="suggestions"></datalist>

  • EDIT

This update (per OP's comment) handles the filtering directly on the <ul> element:

//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)" 
                >
                <ul >
                  <h5 >Top Searches</h5>
                  <li><div >1.3</div></li>
                  <li><div >2.2</div></li>
                  <li><div >3.4</div></li>
                  <li><div >4.5</div></li>
                  <li><div >5</div></li>
                  <li><div >7</div></li>
                  <li><div >8</div></li>
                  <li><div >8.5</div></li>
                  <li><div >9</div></li>
                  <li><div >10</div></li>
                  <li><div >12</div></li>
                  <li><div >14</div></li>
                  <li><div >18</div></li>
                  <li><div >20</div></li>
                  <li><div >22</div></li>
                  <li><div >26</div></li>
                  <li><div >32</div></li>
                  <li><div >33</div></li>
                  <li><div >35</div></li>
                  <li><div >50</div></li>
                  <li><div >55</div></li>
                  <li><div >70</div></li>
                  <li><div >75</div></li>
                  <li><div >100</div></li>
                  <li><div >110</div></li>
                  <li><div >120</div></li>
                  <li><div >155</div></li>
                  <li><div >170</div></li>
                  <li><div >200</div></li>
                  <li><div >220</div></li>
                  <li><div >250</div></li>
                  <li><div >270</div></li>
                  <li><div >300</div></li>
                  <li><div >325</div></li>
                  <li><div >330</div></li>
                  <li><div >400</div></li>
                </ul>
            </li>
          </ul> 
        </form>

  • Related