Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DocumentFragment is losing part of my content

So I'm basicaly just trying move element from one node to an other. I create a fragment and then append to it my children elements.

const fragment = document.createDocumentFragment();
let sortedElements = [...document.querySelectorAll('.product')].sort((a,b) => b.dataset.blockSize - a.dataset.blockSize ); //Select elements
sortedElements.forEach((e) => {
    console.log(e) //My 4 children displayed
    fragment.appendChild(e)
});
console.log(fragment.children); //Only Two children in it

fragment.childNodes.forEach((el) => {
    document.querySelector("#appendThere").appendChild(el);
})
<div class="product" data-object-size="4">Product 1</div>
<div class="product" data-object-size="2">Product 2</div>
<div class="product" data-object-size="1">Product 3</div>
<div class="product" data-object-size="1">Product 4</div>

<div id="appendThere"></div>

Am I missunderstanding how does fragments works ?

It's strangely working on snippet... Even partialy working on my computer But its getting stranger.

enter image description here

enter image description here

I think there is a change between the moment I print my variable and I explore it.

like image 716
Baldráni Avatar asked Oct 22 '25 11:10

Baldráni


1 Answers

You are mutating fragment.childNodes while iterating over it, which is causing the unexpected behavior. You just need to append fragment rather than appending each of it's children.

For example (fixed the element data attributes to correspond to the sort js in your example):

const fragment = document.createDocumentFragment();
const sorted = [...document.querySelectorAll('.product')].sort((a,b) => {
  return b.dataset.blockSize - a.dataset.blockSize;
});

sorted.forEach((elem) => {
  fragment.appendChild(elem);
});

document.querySelector('#destination').appendChild(fragment);
<div class="product" data-block-size="3">Product 2</div>
<div class="product" data-block-size="1">Product 3</div>
<div class="product" data-block-size="4">Product 1</div>
<div class="product" data-block-size="1">Product 4</div>
<div id="destination"></div>

Or, without using a document fragment (may not be a big performance difference if you are working with a limited number of elements).

const destination = document.querySelector('#destination');
const sorted = [...document.querySelectorAll('.product')].sort((a,b) => {
  return b.dataset.blockSize - a.dataset.blockSize;
});

sorted.forEach((elem) => {
  destination.appendChild(elem);
});
<div class="product" data-block-size="3">Product 2</div>
<div class="product" data-block-size="1">Product 3</div>
<div class="product" data-block-size="4">Product 1</div>
<div class="product" data-block-size="1">Product 4</div>
<div id="destination"></div>
like image 137
benvc Avatar answered Oct 24 '25 01:10

benvc



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!