DEV Community

Danish
Danish

Posted on

Searchable list modal component in vanilla js.

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

  1. Create input.
  2. Create modal.
  3. Bind modal show event to input.
  4. Create search input.
  5. Create list element.
  6. Populate list.
  7. Bind listeners to list's element.
  8. 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">
Enter fullscreen mode Exit fullscreen mode

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>


Enter fullscreen mode Exit fullscreen mode

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"); 
}
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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");

Enter fullscreen mode Exit fullscreen mode

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);

Enter fullscreen mode Exit fullscreen mode

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);
    });

}
Enter fullscreen mode Exit fullscreen mode

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 👋🏻

Top comments (3)

Collapse
 
joelbonetr profile image
JoelBonetR 🥇 • Edited

Vanilla JS plus jQuery are incompatible concepts.
You either use Vanilla JS (recommended), which means just standard JS, without libraries/frameworks, or you add jQuery (not recommended since some years ago).

If you add jQuery then it's a jQuery impementation which requires jQuery to run or to run properly (then it's not Vanilla JS).

By the way you can add your code like this:



```js
 // your code here
```


so it gets colorized 🙂

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);
    });
}
Enter fullscreen mode Exit fullscreen mode

Hope this helps somehow 😁👍🏼

Collapse
 
danishkhanzaada profile image
Danish

Thanks for commenting the tips Joel 🙂 Really appreciate it.

Sure Will do that in future posts.

Collapse
 
joelbonetr profile image
JoelBonetR 🥇

You're welcome! 😄