22

I want to create HTMLElement from string by javasacript, like this

element = createHTMLElement('<table class="list"><tr><td><a href="xxx">title</a></td></tr></table>')
element.addEventListener(...)
parent.appendChild(element)

and I do not want to use jQuery

2

3 Answers 3

49

You can create some dummy outer element:

  var div = document.createElement('DIV');

and then:

  div.innerHTML = '<table class="list"><tr><td><a href="xxx">title</a></td></tr></table>'

and then extract it from childNodes:

  div.firstChild

innerHTML is a Microsoft extension, but one universally supported on all modern browsers.

Of course you can form a simple function which does what you want from these snippets.

Sign up to request clarification or add additional context in comments.

3 Comments

Yes, you can reuse it. (replacing innerHTML will release the previous children and instantiate new ones)
Beware, this would not work if the original string had multiple elements at the top level (one after the other). In that case we would have to loop through all the childNodes of the dummy div.
@pasqal Good call, and it's even worse than that. If the string is " <p>some content</p>" (note the space!) then el.firstChild is a text node, not the <p>.
3

Use caution with the top answer as pasqal suggests.

The problem is that .firstChild might not always be what you expect. In my case, I had a single root node (so I thought), but with leading whitespace. Here's a minimal example of my failing code:

const el = document.createElement("div");
el.innerHTML = `
  <p>foo</p>
`;
el.firstChild.classList.add("foo");

The issue is that .firstChild is really a .nodeType === Node.TEXT_NODE:

const el = document.createElement("div");
el.innerHTML = `
  <p>foo</p>
`;
console.log(el.childNodes[0].nodeType === Node.TEXT_NODE);
console.log(el.childNodes[0].textContent);
console.log(el.childNodes[1].nodeType === Node.TEXT_NODE);
console.log(el.childNodes[1].textContent);

How to deal with this is use-case dependent, but you could glue together the non-text nodes with .filter or if you're sure you have one root, as was my case, you can use .firstElementChild:

const el = document.createElement("div");
el.innerHTML = `
  <p>foo</p>
`;
const root = el.firstElementChild;
console.log(root);
root.classList.add("foo"); // works now

2 Comments

better yet... you can use const root = el.firstElementChild
@CITguy good call, updated!
0

You can also append an element using the parent's innerHTML property like this:

        this.parentEl.innerHTML += `
<a-sphere 
  class="a-sim-body"
  dynamic-body 
  position="1 1 1" 
  radius="1" 
  color="blue">
</a-sphere>`

1 Comment

This will break event listeners for nodes already in the parent element as they will be re-created. It will as well cause images to re-render, etc.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.