20

I need to append some html to an existing element using pure javaScript:

function create(htmlStr) {
  var frag = document.createDocumentFragment(),
    temp = document.createElement('div');
  temp.innerHTML = htmlStr;
  while (temp.firstChild) {
    frag.appendChild(temp.firstChild);
  }
  return frag;
}

var target = document.querySelectorAll(".container-right");
var fragment = create(
  '<div class="freetext"><p>Some text that should be appended...</p></div>'
);
document.body.insertBefore(fragment, document.body.childNodes[0]);

It's kind of working, but I have two questions:

  1. How can I make sure that the html fragment is appended to the div with the class container-right and not just the body? Changing the last line to document.body.insertBefore(fragment, target); doesn't work.

  2. How can I insert the html after the content in the target element - after the existing content - like jQuery's append()?

Any help is much appreciated.

JsFiddle here.

Meek
  • 3,086
  • 9
  • 38
  • 64
  • You might be better off creating a div (`var div = document.createElement('div');`), setting its html (`div.innerHTML = "Hello World!";`), and appending it to the body (`document.body.appendChild(div);`) – Marie Feb 28 '17 at 20:04
  • 1
    `document.querySelectorAll()` returns a [NodeList](https://developer.mozilla.org/en-US/docs/Web/API/NodeList), so you'll want `document.body.insertBefore(fragment, target[0]);`. – Elliot Bonneville Feb 28 '17 at 20:04

6 Answers6

34

Well, I know this works:

let elem = document.querySelector ( 'css-selector (id or class)' )

That should give you your element. Then you do this:

elem.innerHTML = elem.innerHTML + myNewStuff;

That'll append your html to the innerHTML of the element. I tried it quickly, it works.

Tim Consolazio
  • 4,802
  • 2
  • 19
  • 28
  • 6
    Be careful modifying the innerHTML property of an existing element directly. It may cause issues with any events bound to child-objects. – Marie Feb 28 '17 at 20:06
  • Yah agreed, you should always be mindful when directly manipulating DOM elements. I personally prefer using documentFragment, but as long as you know what you're doing this works. Unless I had a very good reason to, I wouldn't do this for an interactive element, only an element that displays static stuff. – Tim Consolazio Feb 28 '17 at 20:07
  • 1
    documentFragment and the API it affords is the same idea as manipulating XML as a string (which is more or less what we're doing here) vs. using nodes to manipulate a parse-able structure in an object oriented way (more or less). If you look up "document.createDocumentFragment" you'll see what it's all about. In the vanilla JS world it is a very powerful way to work with creating, structuring, altering, and moving around HTML elements. Definitely a more robust way than messing around with innerHTML of live, currently displayed DOM elements (and higher performance if I recall correctly). – Tim Consolazio Feb 28 '17 at 20:12
  • 3
    Ammm `elem.innerHTML += myNewStuff;` seems more readable and simpler. – Roko C. Buljan Mar 30 '20 at 12:19
  • 1
    Ammm then set up a helpful edit suggestion (I certainly hope you don't say Ammm in your code reviews). – Tim Consolazio Mar 30 '20 at 12:28
28
var target = document.querySelector(".container-right");

var p = document.createElement('p');
p.innerHTML = "Some text that should be appended...";

var div = document.createElement('div');
div.appendChild(p);

var fragment = document.createDocumentFragment();
fragment.appendChild(div);

target.appendChild(fragment);

JSFiddle

Paulo Pereira
  • 1,064
  • 8
  • 16
  • This is MUCH more performant than the accepted answer. If you're dealing with a large element, the browser will re-render the entire thing rather than just the element you're appending. – Christopher May 14 '19 at 18:15
  • The accepted answer does point out/suggest document fragment, followed a couple of minutes later by this one... – Tim Consolazio Mar 30 '20 at 12:29
  • The problem with this solution is references, when element is appended, p, div, and fragment variables are now a dom references, so, if you modify one of them after appended, dom will be modified too, and that is something I dont expect, if I am dinamically generating multiple items (duplicates) then will fail because there will be just one element, instead N elements. – Máxima Alekz Jan 10 '21 at 08:06
  • @MáximaAlekz there is no sense in your comment. First, the question is not about multiple items. Second, it is the best thing to have dom reference because you can modify without querying again for the element. And last, answering you, if you have multiple items, declare multiple variables or reuse the same variable after appending (if you don’t care about the dom). – Paulo Pereira Jan 10 '21 at 14:02
8

Try this:

var target = document.querySelector(".container-right");
target.innerHTML += '<div class="freetext"><p>Some text that should be appended...</p></div>';
Justin Taddei
  • 2,142
  • 1
  • 16
  • 30
7

Based on this answer to a similar question, I have found that insertAdjacentHTML is a good fit for this kind of problems. I haven't tested it on a Node List, but with a single node it works perfectly.

insertAdjacentHTML has a great browser compatibility (back to IE4), plus it lets you decide where you want to insert the HTML (see here).

var target = document.querySelector(".container-right");
var newContent = '<div class="freetext"><p>Some text that should be appended...</p></div>';
target.insertAdjacentHTML('beforeend', newContent);
Giorgio Tempesta
  • 1,816
  • 24
  • 32
0
document.querySelectorAll('.container-right').forEach(elm=>{
    elm.innerHTML += '<div class="freetext"><p>Some text that should be appended...</p></div>';
});
  • 2
    Please don't post code-only answers. The main audience, future readers, will be grateful to see explained *why* this answers the question instead of having to infer it from the code. Also, since this is an old, well answered question, please explain how it complements the other answers. – Gert Arnold Dec 18 '22 at 19:46
  • Thank you for leaving a comment to help me provide a better answer. That's why I answered this old question: We know that js and css files will load fully. we also know that hard drives are hundreds of thousands of times slower than RAM. Therefore, the number and volume of files that need to be loaded will greatly decrease the loading speed of websites. That's why I obsess over verbatim of js and css codes. And I try to write them as short as possible. in addition, we waste more time every time we try to find an element in the document. So it is better to try to reach our goal with ... – babak-maziar Dec 23 '22 at 21:50
  • Continuation of the previous comment: minimum search in the document. Of course this is not the only thing that i done to Increase loading speed, but this obsession causes the loading speed of the worst my websites to be less than 3 seconds. Meanwhile, the internet speed in Iran is lower than the global internet speed. I tried to share my experience and personal solutions with others. – babak-maziar Dec 23 '22 at 21:51
  • Please [edit] your answer. – Gert Arnold Dec 23 '22 at 21:54
0

You should always use the version from @Giorgio Tempesta

var target = document.querySelector(".container-right");
var newContent = '<div class="freetext"><p>Some text that should be appended...</p></div>';
target.insertAdjacentHTML('beforeend', newContent);

By using the elm.innerHTML += ... method, you will always lose all eventlisteners, that may be initialized before.

For example: If your div looks like this:

<div class="menu">
    <input id="test type="checkbox" name="test"/>
</div>`

And there is a Eventlistener like document.querySelector('#test').addEventListener('click', ...) you will delete this EventListener if you use innerHTML on the outer div element.

var target = document.querySelector(".menu");
target.innerHTML += ...
Florian
  • 1
  • 1