Emptying value doesn't return original filtered options

Issue

I’m trying to get all the original li’s back once I clear the input. The problem is it .value = ” clears the input but the filter is still applied.

I’d appreciate help on this, it’s driving me crazy.

(I removed the CSS but you can still get a pretty good idea, thx)

var myInput = document.getElementById('myInput');


function myFunction() {
    var input, filter, ul, li, a, i, txtValue;
    input = document.getElementById("myInput");
    filter = input.value.toUpperCase();
    ul = document.getElementById("myUL");
    li = ul.getElementsByTagName("li");
    for (i = 0; i < li.length; i++) {
        a = li[i].getElementsByTagName("a")[0];
        txtValue = a.textContent || a.innerText;
        if (txtValue.toUpperCase().indexOf(filter) > -1) {
            li[i].style.display = "";
        } else {
            li[i].style.display = "none";
        }
    }
}

var h2 = document.getElementById('hh');
h2.addEventListener('click', clear);

function clear() {
    myInput.value = '';
}
<h2 id="hh">Click here to empty input</h2>

<input type="text" id="myInput" onkeyup="myFunction()" placeholder="Search for names.." title="Type in a name">

<ul id="myUL">
  <li><a href="#">Adele</a></li>
  <li><a href="#">Agnes</a></li>

  <li><a href="#">Billy</a></li>
  <li><a href="#">Bob</a></li>

  <li><a href="#">Calvin</a></li>
  <li><a href="#">Christina</a></li>
  <li><a href="#">Cindy</a></li>
</ul>

Solution

The filter itself is not "applied", it’s the consequences of it that are.

When you look at your code, you’ll find that you have, at a point, set to display: none the <li> that were not matching your filter.

Your clear() function reset the value of the input, without reversing the changes made to the <li> that you did by applying display: none.

You have to make your clear() function also remove the display: none out of all <li> stored in your array by iterating through that same array and reversing the changes made to the display property.

    const myInput = document.getElementById('myInput');
    const ul = document.getElementById("myUL");
    const list = ul.children
    
    function myFunction() {
        const input = document.getElementById("myInput");
        const filter = input.value.toUpperCase();   
        for (i = 0; i < list.length; i++) {
            const a = list[i].getElementsByTagName("a")[0];
            const txtValue = a.textContent || a.innerText;
            if (txtValue.toUpperCase().indexOf(filter) > -1) {
                list[i].style.display = "";
            } else {
                list[i].style.display = "none";
            }
        }
    }
    
    var h2 = document.getElementById('hh');
    h2.addEventListener('click', clear);
    
    function clear() {
        for(i = 0; i < list.length; i++) {
            list[i].style.display = "";
        }
        myInput.value = '';
    }

Instead of using ul.getElementsByTagName("li"), you should use as I did above ul.children, which stores the childrens of the selected parent into an array, and the childrens of an <ul> are essentially all <li>, so.

The code above works and clear out the filter as you wanted to.
I would recommend you to not use var, only const, let that will prevent many errors while manipulating variables throughout your code overall.
Please consider them.

Answered By – Slice

Answer Checked By – Terry (AngularFixing Volunteer)

Leave a Reply

Your email address will not be published.