Search code examples
javascriptfor-loopappendappendchild

For loop and add <li> to <ul> multiple times


I know this should be relatively simple, but trying to get this to work...

  • I have 3 divs, which contain <li>'s.
  • I want to loop through all my divs, (by classname .fare-benefits).
  • To find the div, which only has 1 <li>.
  • Once I've looped through and found the div, with only 1 <li>, I want to add an additional 8 empty <li>'s, to it's parent <ul>.

For some reason, I keep getting the following error:

"Uncaught TypeError: Cannot read property 'appendChild' of undefined"

I've created an example of my code below. Any pointers?

let fareBenefitsDiv = document.querySelectorAll(".fare-benefits");

  for (let i = 0; i < fareBenefitsDiv.length; i++) {
  
    if (fareBenefitsDiv[i].childElementCount === 1) {
      for (let i = 0; i < 9; i++) {
        let createLI = document.createElement("li");
        createLI.classList.add("fare-benefit");
        fareBenefitsDiv[i].appendChild(createLI);
      };
   };
};
.cards {
  border: 1px solid grey;
  width: 300px;
  display: flex;
}

ul {
  list-style: none;
}

.fare-benefit {

  border-bottom: 1px solid grey;
}
<div class="cards">

  <div class="row-1 fare-benefits">
    <ul>
      <li class="fare-benefit">1</li>
    </ul>
  </div>
  
  <div class="row-2 fare-benefits">
    <ul>
        <li class="fare-benefit">1</li>
        <li class="fare-benefit">2</li>
        <li class="fare-benefit">3</li>
        <li class="fare-benefit">4</li>
        <li class="fare-benefit">5</li>
    </ul>
  </div>
  
  <div class="row-3 fare-benefits">
    <ul>
      <li class="fare-benefit">1</li>
      <li class="fare-benefit">2</li>
      <li class="fare-benefit">3</li>
      <li class="fare-benefit">4</li>
      <li class="fare-benefit">5</li>
      <li class="fare-benefit">6</li>
      <li class="fare-benefit">7</li>
      <li class="fare-benefit">8</li>
      <li class="fare-benefit">9</li>
    </ul>
  </div>
  
</div>


Solution

  • As mentioned in the comments, you're reusing the variable i. So when you use fareBenefitsDiv[i].appendChild(createLI); it's using the i that counts the number of <li> to add, not the index of the DIV.

    You can avoid problems like this, and also simplify code, by using forEach instead of a for loop.

    Another problem in your code is that all the DIVs only have one child element, the <ul>. You should be iterating over the <ul> elements and appending to them, not the DIV.

    let fareBenefitsUL = document.querySelectorAll(".fare-benefits ul");
    fareBenefitsUL.forEach(ul => {
      if (ul.childElementCount === 1) {
        for (let i = 0; i < 8; i++) {
          let createLI = document.createElement("li");
          createLI.classList.add("fare-benefit");
          createLI.innerText = 'x';
          ul.appendChild(createLI);
        };
      };
    });
    .cards {
      border: 1px solid grey;
      width: 300px;
      display: flex;
    }
    
    ul {
      list-style: none;
    }
    
    .fare-benefit {
      border-bottom: 1px solid grey;
    }
    <div class="cards">
    
      <div class="row-1 fare-benefits">
        <ul>
          <li class="fare-benefit">1</li>
        </ul>
      </div>
    
      <div class="row-2 fare-benefits">
        <ul>
          <li class="fare-benefit">1</li>
          <li class="fare-benefit">2</li>
          <li class="fare-benefit">3</li>
          <li class="fare-benefit">4</li>
          <li class="fare-benefit">5</li>
        </ul>
      </div>
    
      <div class="row-3 fare-benefits">
        <ul>
          <li class="fare-benefit">1</li>
          <li class="fare-benefit">2</li>
          <li class="fare-benefit">3</li>
          <li class="fare-benefit">4</li>
          <li class="fare-benefit">5</li>
          <li class="fare-benefit">6</li>
          <li class="fare-benefit">7</li>
          <li class="fare-benefit">8</li>
          <li class="fare-benefit">9</li>
        </ul>
      </div>
    
    </div>