Rayyan
Rayyan

Reputation: 17

Why is innerHTML acting weird

So I'm making a javascript file that uses a loop to make the times tables 1 to 12, but I use css to make a neat feel by making any element with the class of timetable float to the right. However the divs which seperate each time table and have a class of timetable do not have any children. Im trying to make the p elements which hold one time table be the children of the divs. Here's my code:

    var math = document.getElementById("maths");

     for (var num = 1; num <= 12; num++) {
         math.innerHTML += "<div class=\"timetable\">";
         for (var currentMath = 1; currentMath <= 12; currentMath++) {
             math.innerHTML += "<p>" + num + " x " + currentMath + " = " + (num * currentMath) + " 
      </p>";
         }
         math.innerHTML += "</div>";
     }

Expected HTML:

<div class="timetable"><p>1 x 1 = 1</p>....</div>

HTML:

<div class="timetable"></div><p>1x1 = 1</p>...

Can anyone help me?

Upvotes: 1

Views: 181

Answers (3)

Maniraj Murugan
Maniraj Murugan

Reputation: 9084

Please create HTML element using document.createElement() and append the child elements (which is considered as best practice) instead of assigning it as a string.

With the help of appendChild() , you can append child element to the parent.

Working Example:

const math = document.getElementById("maths");

 for (let num = 1; num <= 12; num++) {
     const timeTable = document.createElement('div');
     timeTable.classList.add('timetable');
     for (let currentMath = 1; currentMath <= 12; currentMath++) {
          const child = document.createElement('p');
          child.textContent = num + " x " + currentMath + " = " + (num * currentMath)
          timeTable.appendChild(child);
     }
     math.appendChild(timeTable);
 }
<div id="maths"></div>

Upvotes: 2

connexo
connexo

Reputation: 56783

Q: Why is innerHTML acting weird?

A: Because you're doing weird stuff with it.

Your issue is that you are trying to assign unclosed elements to innerHTML. Strings you assign here must always be complete, because any string you assign is going to be parsed to actual, valid HTML. This means that the way you are doing things the browser will close the unclosed div for you:

math.innerHTML += "<div class=\"timetable\">";

will result in the browser closing the div for you:

<div class="timetable"></div>

After that, you append <p>....whatever...</p> to innerHTML repeatedly in a loop, resulting in this innerHTML:

<div class="timetable"></div>
<p>....whatever...</p>
<p>....whatever...</p>
<p>....whatever...</p>

As you can see, the p elements are not children of the div.timetable.

To fix your issue, just build your string before assigning it (and use template literals to do that):

const math = document.getElementById("maths");
let html = '';

for (let num = 1; num <= 12; num++) {
    html += `<div class="timetable">`;
    for (let currentMath = 1; currentMath <= 12; currentMath++) {
        html += `<p>${num} x ${currentMath} = ${num * currentMath}</p>`;
    }
    html += "</div>";
}
math.innerHTML = html;
<div id="maths"></div>

Also, don't use var any more in 2022, use const as a default, and use let if you know you will have to repeatedly assign to the variable. var should only be used if you explicitly need the specific scoping behavior it has.

Upvotes: 3

Archit Gargi
Archit Gargi

Reputation: 685

The below code should work. You didn't add any HTML though so I am not sure it will work on your end but try it...

var math = document.getElementById("maths").innerHTML;
var code = math;
for (var num = 1; num <= 12; num++) {
  code += "<div class=\"timetable\">";
  for (var currentMath = 1; currentMath <= 12; currentMath++) {
    code += "<p>" + num + " x " + currentMath + " = " + (num * currentMath) + " </p>";
  }
  code += "</div>";
  document.getElementById("maths").innerHTML += code;
  code = "";
}
<div id="maths"></div>

Upvotes: -1

Related Questions