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.
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>