8

Is there a way to convert markup string to node object in JavaScript? Actually I am looking for the subsitute for:

document.getElementById("divOne").innerHTML += "<table><tbody><tr><td><input type='text' value='0' /></td></tr></tbody></table>"

something like

document.getElementById("divOne").appendChild(document.createNodeFromString("<table><tbody><tr><td><input type='text' value='0' /></td></tr></tbody></table>"))

using createNodeFromString rather creating the table element then append its child elements then attach their respective attributes and values!

8
  • 1
    I am curious why setting innerHTML does not work for you. After you set innerHTML you can get the resulting element by querying your divOne. Commented Feb 17, 2012 at 20:08
  • @akonsu, supposedly you have <input type=text /> in divOne and outside this div you have a button with onclick= innerHTML-method. Now, in FF10 and IE9 (with document mode IE9) enter something in the textbox and press the button, the value of input would be reset! I am trying to see would same thing happen with appendChild. Btw, in IE8 compatibility mode, the value of input element is persistent.. Commented Feb 17, 2012 at 20:17
  • are you saying that if you have a text input field and a button, the value of the input field gets cleared when you press the button? could you demonstrate this on, say, jsbin.com? Commented Feb 17, 2012 at 20:26
  • Have you considered using a framework such as jQuery? Makes that kind of task much easier... Commented Feb 17, 2012 at 20:29
  • Try it in FF10 or IE9 with native compatibility and then in IE8 compatibility mode: jsbin.com/amodag Also, document.getElementById("divOne").appendChild(document.createElement("input")) does retain the value of input in IE9 but I need to append the entire table in a single statement. Commented Feb 17, 2012 at 20:31

4 Answers 4

17

There's not an existing cross-browser function for this. The following method can be used to achieve the desired effect (using a DocumentFragment for an optimized performance, based on this answer):

function appendStringAsNodes(element, html) {
    var frag = document.createDocumentFragment(),
        tmp = document.createElement('body'), child;
    tmp.innerHTML = html;
    // Append elements in a loop to a DocumentFragment, so that the browser does
    // not re-render the document for each node
    while (child = tmp.firstChild) {
        frag.appendChild(child);
    }
    element.appendChild(frag); // Now, append all elements at once
    frag = tmp = null;
}

Usage (indention for readability):

appendStringAsNodes(
    document.getElementById("divOne"),
   "<table><tbody><tr><td><input type='text' value='0' /></td></tr></tbody></table>"
);
Sign up to request clarification or add additional context in comments.

Comments

4

Yes, you can do that.

var myNewTable = document.createElement("table");
myNewTable.innerHTML = "<tbody><tr><td><input type='text' value='0' /></td></tr></tbody>"
document.getElementById("divOne").appendChild(myNewTable);

1 Comment

Older IE versions will complain about this, because they cannot handle setting the innerHTML property on some elements, including <table>. See also this article.
1

some news on this topic:

the modern approach is to use the <template> tag, which you place e.g. before the body closes (the browser will ignore it).

it's a standardization of client side templating, and doesn't need to use .innerHTML, which could lead to security issues (XSS)

example:

<template id='tplArticle'>
  <article class='newsItem'>
    <h1 class='title'></h1>
    <p class='paragraph'>
  </article>
</template>

whenever you need it, you just grab its content and clone (!!) it to reuse it:

// .content will grab the content of the template, not the <template> tag
// this will return a document fragment
const $articleFragment = document.querySelector('#tplArticle').content;

// clone it, otherwise you get the same reference and it won't be reusable (true makes a deep copy)
const $article = document.importNode($articleFragment, true);

// then e.g. append it to the body
document.body.appendChild($article);

2 Comments

Nice and efficient, thanks! caniuse.com/?search=%3Ctemplate%3E suggests that we should just use it in this day and age.
also nice to check out: WebComponents: developer.mozilla.org/en-US/docs/Web/Web_Components (<template>, <slot>, Shadow DOM, Custom Elements) 2) medium.com/swlh/functional-web-components-90a0edc2aa90 for functional programming friends like me: great article whether to use functional or OOP for WebComponents (or in general)
0
function htmlMarkupToNode(html){
    let template = document.createElement("template");        
    template.innerHTML = html ;
    let node = template.content.cloneNode(true) ;        
    return node ;   
}

document.getElementById("divOne").appendChild(htmlMarkupToNode("<table><tbody><tr><td><input type='text' value='0' /></td></tr></tbody></table>"));

1 Comment

ah, just seen your post now, sorry for adding it myself, I've tried to be a bit more detailed though... btw you can add the language of the code (to format it) by adding the language name after the 3 backticks

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.