Searchable list modal component in vanilla js.
Danish
Posted on June 28, 2022
Peace be upon you - السلام عليكم
The Why
I was using a dropdown to search data of about 22k to 52k of size, dropdown was hanging as it rendered 22k list items at once.
So, I wanted to create my custom searchable list like Trading View's Search, on clicking the input a modal appears and we can search the data, then click on the searched value and it appears on our initial input.
The Steps
- Create input.
- Create modal.
- Bind modal show event to input.
- Create search input.
- Create list element.
- Populate list.
- Bind listeners to list's element.
- Bind search functionality to search input and list.
Technologies used
- Bootstrap 4
- Vanilla JS
- jQuery
Implementation
First: Create a simple input element and give it a unique id.
This input is used for opening up the selector modal and showing the selected value from the modal.
<input type="text" class="form-control" placeholder="Select Item From List" id="searchModalOpener">
Second: Create a modal, give it a unique id.
<div class="modal " id="searchModalOpener-modal" data-backdrop="static">
<div class="modal-dialog modal-lg" style="height: 600px">
<div class="modal-content h-100 rounded-4">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
</div>
<div class="modal-body"> </div>
</div>
</div>
</div>
Note: Add the modal as direct child to body or inside a div which is direct child to body.
Third: Bind show event to open modal when clicked on input.
document.getElementById("searchModalOpener").onclick = () => {
$(`searchModalOpener-modal`).modal("show");
}
Fourth and Fifth: Adding search input and list (with unique id's) in modal body
<div class="modal-body">
<input type="text" class="form-control" style="text-align: center" placeholder="Search Symbol" id="searchModalOpener-search">
<div id="searchModalOpener-list" style="height: 400px" class="overflow-auto pb-5"></div>
</div>
Sixth: Populate the list with your data
There can be dozens of ways to achieve it and mine may not be the best so you can be creative in here, I am iterating over the data array and on each iteration I create a p element, style it, add its text value and attach event listener to it so that on click its value gets set on our initial input element, and at last I append it to our list element.
//data: string[] = ["1", "2", "3"];
let list = document.querySelector(`#searchModalOpener-list`);
const addItemToList = (val) => {
let tag = document.createElement("p");
tag.id = "p-symbol"
tag.classList.add(...["my-2", "border-bottom", "py-1"])
let text = document.createTextNode(val);
tag.appendChild(text);
list.appendChild(tag);
}
function populateList() {
data.forEach((val, index) => {
addItemToList(val);
});
}
//Call populateList Method when you are opening the modal, i.e bind it to the shown event of modal
//Above code becomes
$(`searchModalOpener-modal`).on('show.bs.modal', function() {
listPopulate();
}).modal("show");
Seven: Add listener to list item
// Create a function and bind it to p tag before appending it to the list
let firstInput = document.querySelector("#searchModalOpener");
cost itemOnClick = (val) => {
firstInput.setAttribute("value", val);
}
// Add this next line in addItemToList Function just before appending it
tag.onclick = () => itemOnClick(val);
Eight: Bind search functionality to search bar.
const searchBar = document.querySelector(`#searchModalOpener-search`);
searchBar.addEventListener('input', function(e) {
const query = e.target.value;
if (query.length > 0) {
list.innerHTML = ``;
const filteredList = data.filter(val => val.trim().startsWith(query.toUpperCase()));
filteredList.forEach((val, index) => {
addItemToList(val);
});
}
Puff! All done, Feel free to ask anything. Thanks.
PS: After's Joel's comment, it is highly recommended now to just use Vanilla JS, my reason to use jquery was only for modal events, they were not running with document method.
Happy Coding 👋🏻
Posted on June 28, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.