dcangulo
dcangulo

Reputation: 2107

getElementsByClassName and appendChild is not working as expected

First of all, solutions must be pure VanillaJS.

I have a simple HTML code.

<div class="x">X</div>
<div class="x">Y</div>
<div class="x">Z</div>

And a VanillaJS code.

document.addEventListener('DOMContentLoaded', function() {
    var l = document.createElement('div');
    l.innerHTML = "Hello World";
}, false);

When I tried to run the following code:

document.getElementsByClassName('x')[0].appendChild(l);

I get the output

X
Hello World
Y
Z

Well, technically that is correct. But whenever I tried to append to another member of the array it does not work as expected.

I have tried:

document.getElementsByClassName('x')[0].appendChild(l);
document.getElementsByClassName('x')[1].appendChild(l);
document.getElementsByClassName('x')[2].appendChild(l);

EXPECTED OUTPUT:

X
Hello World
Y
Hello World
Z
Hello World

ACTUAL OUTPUT

X
Y
Z
Hello World

Based on my observation, only the last line of the code is considered. There were no errors in the console, it just simply not working.

I have tried another scenario of rearranging the order of the array.

document.getElementsByClassName('x')[1].appendChild(l);
document.getElementsByClassName('x')[2].appendChild(l);
document.getElementsByClassName('x')[0].appendChild(l);

EXPECTED OUTPUT:

X
Hello World
Y
Hello World
Z
Hello World

ACTUAL OUTPUT:

X
Hello World
Y
Z

As you can see, only the last append is considered, it does not append on the other elements with the same class name.

I also tried looping them, still no luck.

FULL CODE:

<div class="x">X</div>
<div class="x">Y</div>
<div class="x">Z</div>

<script>
document.addEventListener('DOMContentLoaded', function() {
   var l = document.createElement('div');
    l.innerHTML = "Hello World";

    document.getElementsByClassName('x')[0].appendChild(l);
    document.getElementsByClassName('x')[1].appendChild(l);
    document.getElementsByClassName('x')[2].appendChild(l);
}, false);
</script>

Upvotes: 2

Views: 2885

Answers (3)

I. Ahmed
I. Ahmed

Reputation: 2534

This occurred because you used one HTMLElement reference to add as child for all the div. One html child can be added to one parent only. So, first two parents append child appended the element, then immediately removed and finally add it as child of last div only.

I have created 3 different child for all div. Please check the following code snippet:

<div class="x">X</div>
<div class="x">Y</div>
<div class="x">Z</div>

<script>
document.addEventListener('DOMContentLoaded', function() {
   var l1 = document.createElement('div');
    l1.innerHTML = "Hello World";
    var l2 = document.createElement('div');
    l2.innerHTML = "Hello World";
    var l3 = document.createElement('div');
    l3.innerHTML = "Hello World";

    document.getElementsByClassName('x')[0].appendChild(l1);
    document.getElementsByClassName('x')[1].appendChild(l2);
    document.getElementsByClassName('x')[2].appendChild(l3);
}, false);
</script>

Upvotes: 1

Taki
Taki

Reputation: 17654

you can use cloneNode to append copies of the created element :

document.addEventListener('DOMContentLoaded', function() {
  var l = document.createElement('div');
  l.innerHTML = "Hello World";

  document.getElementsByClassName('x')[0].appendChild(l.cloneNode(true));
  document.getElementsByClassName('x')[1].appendChild(l.cloneNode(true));
  document.getElementsByClassName('x')[2].appendChild(l.cloneNode(true));
}, false);
<div class="x">X</div>
<div class="x">Y</div>
<div class="x">Z</div>

Upvotes: 3

CertainPerformance
CertainPerformance

Reputation: 370779

You only ever create a single element:

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

When you use appendChild, if the appended element is currently a child of some other parent (eg the first x), when you append it to another, it gets removed from its first parent and is appended to the second. Appending the same element to multiple parents in a row will result in it only existing as a child of the last parent at the end.

Create a new element on each iteration instead (and when assigning text and not HTML, make sure to assign to the textContent property rather than the innerHTML property)

document.querySelectorAll('.x').forEach((x) => {
  var l = document.createElement('div');
  l.textContent = "Hello World";
  x.appendChild(l);
});
<div class="x">X</div>
<div class="x">Y</div>
<div class="x">Z</div>

Upvotes: 4

Related Questions