0

When generating HTML with JavaScript, is it better to use the annoyingly verbose document.createElement("p")...

(as seen here: https://www.w3schools.com/jsref/met_document_createelement.asp )

or is it better to use template literals (back-ticks)?

`<p></p>`

I'm not sure if template literals updates the DOM or not & I assume that the createElement() does?

And I don't know how to test it.

Example code:

<body>
  <div id="myDIV"></div>

  <script>

    let theDiv = document.getElementById("myDIV");

    function verboseGeneration(){
      var para = document.createElement("P");
      para.innerHTML = "This is a paragraph.";
      theDiv.insertAdjacentElement("beforeend", para);
    }

    function TemplateLiteralGeneration(){
        theDiv.insertAdjacentHTML("beforeend", `<p>This is a paragraph.</p>`)
    }

    verboseGeneration();
    TemplateLiteralGeneration();

  </script>
</body>

Expected result: They are equal.

Actual result: Unknown, since I don't know how to test how it interact with the HTML DOM.

(I'm planning on generating a big table based on some arrays, and I'm hesitant to use Template Literals in case they don't update or don't work properly with the DOM and it creates weird issues in the future.)

Sebastian Norr
  • 7,686
  • 2
  • 12
  • 17
  • 1
    Template literals don't do anything. They are just evaluated to a string value, nothing else. What updates the DOM is your `innerHTML` assignment, and it absolutely doesn't matter for that how the string came into existence. – Bergi Jul 25 '19 at 12:56

1 Answers1

1

It depends on what you want to do with the generated markup. If you want to perform manipulation, traverse fragment, then you are better off creating an element as a node (using document.createElement()), instead of using plain string.

And as you mentioned that you are generating a big table, it might make more sense (and likely more performant) to actually create a document fragment that holds all the contents of your large table, and then append the entire fragment into a blank <table> element.

Here is an example: I want to iteratively create a table that is 10 columns wide and 20 rows tall. If you choose to construct the entire table using plain string, the string will become very long, and you can't traverse through the created table if you want to.

The example below shows how powerful using document.createElement() and fragments can be: I can retroactively apply new style and logic to the markup by traversing through it. You cannot do that with plain strings. In this case, I choose to revisit the table at the end, and conditionally highlight cells that have even nubmers in them:

const fragment = document.createDocumentFragment();
const columns = 10;
const rows = 20;

// Create table header
const header = document.createElement('thead');
const headerRow = document.createElement('tr');
for (let i = 0; i < columns; i++) {
  const headerCell = document.createElement('th');
  headerCell.innerHTML = `Col ${i + 1}`;
  headerRow.appendChild(headerCell);
}
header.appendChild(headerRow);

// Append header to table
fragment.appendChild(header);

// Create table body
const body = document.createElement('tbody');

for (let i = 0; i < rows; i++) {
  const bodyRow = document.createElement('tr');
  for (let j = 0; j < columns; j++) {
    const bodyCell = document.createElement('td');
    bodyCell.innerHTML = i + j + 1;
    bodyRow.appendChild(bodyCell);
  }
  
  body.appendChild(bodyRow);
}

// Append body to table
fragment.appendChild(body);

// Here's the advantage of storing your markup as node/elements
// You can traverse through the fragment if you want!
// Let's say I want to highlight all even numbers
const allCells = fragment.querySelectorAll('tbody td');
Array.from(allCells).forEach(cell => {
  const n = +cell.innerHTML;
  if (n % 2 === 0) {
    cell.classList.add('highlight');
  }
});

document.getElementById('my-table').appendChild(fragment);
table th,
table td {
  border: 1px solid #ccc;
}

.highlight {
  background-color: yellow;
}
<table id="my-table"></table>
Terry
  • 63,248
  • 15
  • 96
  • 118
  • Thanks! I learned about the createDocumentFragment() from this, it will be very usefull. As thank you, did you know about [insertAdjacentHTML()](https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML) ? use that instead of innerHTML, it doesn't cause an expensive DOM reFlow as the [innerHTML](https://stackoverflow.com/a/33995479/7880517) does. – Sebastian Norr Jul 26 '19 at 07:15
  • Thank you very much , this is really what i need too.createDocumentFragment() is really awesome. – Jb Randria Aug 25 '21 at 07:52