3

I need to hide/show an <li> based on its text content. In the example below, I want to only show the list item that contains "content 1" and hide the rest of the list items. I'm sure there are several ways to do this. Would I need to convert the list to an array and then use the "includes" method, then append style display none/ display block using a conditional statement?

I would have several unordered lists on a page and therefore target them with the wrapper div's ID.

 <div id="myDiv">
    <ul class="myList">
        <li>content 1</li>   
        <li>content 2</li>  
        <li>content 3</li>   
        <li>content 4</li>     
     </ul>
   </div>
Espskully
  • 97
  • 1
  • 2
  • 10

3 Answers3

5

As in the subject you ask for a JavaScript solution, here is one. Iterate the li elements involved and set their display style depending on their text content:

for (let li of document.querySelectorAll("#myDiv li")) {
    li.style.display = li.textContent === "content 1" ? "" : "none";
}
<div id="myDiv">
  <ul class="myList">
    <li>content 1</li>
    <li>content 2</li>
    <li>content 3</li>
    <li>content 4</li>
  </ul>
</div>
trincot
  • 317,000
  • 35
  • 244
  • 286
  • This is interesting shorthand. I see what's happening, but am a bit puzzled that this order of things works. That the style statement = the text Content, then the triple equals, then the conditional. – Espskully Jul 27 '21 at 19:39
  • 1
    Operators have a priority: First equality (`===`), then ternary (`? :`), then assignment (`=`). And I skipped over the member access (`.`) operator, which really comes first. – trincot Jul 27 '21 at 19:54
  • I swapped out the triple equals for .includes. Does includes have the same priority as triple equals? I'm still a bit confused on the order of things. Even with your explanation of priority - what's determining the order of things here, as it seems to be unintuitive when I try to square it with the priority. Apologies - I'm a total newb. – Espskully Jul 27 '21 at 20:55
  • 1
    With `includes` it will work fine too. So the order (with `===`) is: `li.textContent === "content 1"`. Then the ternary operator is evaluated, so if the `===` expression evaluates to true, then it evaluates to `""`, else to `"none"`. Then the assignment of that string happens next, and so we get `li.style.display = "none"` (or `""`). – trincot Jul 27 '21 at 21:01
  • I guess what's throwing me is that the code is seemingly not written in the order of precedence. – Espskully Jul 27 '21 at 21:07
2
  1. If you want to achieve the text of an element, then you should use TextContent or innerHtml. textContent is more preferred because of some security issues and the latest syntax.
  2. You can also use indexOf() method to check if some string in the element exists or not. It is a string method. A similar syntax for this one is Node.textContent.indexOf("word") != -1).
  3. Don't forget that you have more than one li tag so you must check the value of them with a loop(for). Preferably for let foo of bar.

const li = document.querySelectorAll('li');

document.querySelector('button').addEventListener('click', () => {
  for (let x of li) {
    if (x.textContent === 'content1') {
      x.style.display = 'none';
    } else {
      x.style.display = 'block';
    }
  }
});
<ul>
  <li>content1</li>
  <li>content2</li>
  <li>content3</li>
</ul>

<button type="button">Hide</button>
Amini
  • 1,620
  • 1
  • 8
  • 26
2

My suggestion:

[...document.querySelectorAll('.myList li')]
.forEach(li => li.style.display = li.innerText === 'content 1' ? 'block' : 'none');
<div id="myDiv">
  <ul class="myList">
    <li>content 1</li>
    <li>content 2</li>
    <li>content 3</li>
    <li>content 4</li>
  </ul>
</div>

Alternatively:

[...document.querySelectorAll('.myList li')]
.forEach(li => {
  'content 1' !== li.innerText && (li.style.display = 'none')
});
<div id="myDiv">
  <ul class="myList">
    <li>content 1</li>
    <li>content 2</li>
    <li>content 3</li>
    <li>content 4</li>
  </ul>
</div>
AbsoluteBeginner
  • 2,160
  • 3
  • 11
  • 21