retain reference to appended node javascript
Asked Answered
D

6

12

No libraries please. Beyond my control.

I'm appending a document fragment to the dom. THIS ALL WORKS. No problemo.

How do I retain/retrieve the node list after the fragment is appended? Relevant code:

var frag = document.createDocumentFragment();
//add some content to the fragment
element.appendChild(frag);

Again, this works! I do NOT need a troubleshoot on how to add things to the dom!

If I set var e = element.appendChild(frag);, everything gets appended normally, but e = an empty document fragment.

I'm looking for some smooth magic voodoo here. Don't send me looping over the entire dom. The content could be anything, one or many nodes with or without children. If there's some trick with querySelectorAll or something that would be acceptable.

Thanks!

EDIT Upon further poking, it appears that e above is in fact a returned reference to the frag var, that is empty after appending it to the dom. It's much like the elements were neatly slid off of the fragment into the dom, and the fragment just lays around empty.

Dyslogia answered 9/11, 2012 at 20:25 Comment(0)
C
21

It's exactly what you've described; when the elements are appended to an element, they're removed from the fragment to prevent memory leaks from lingering references.

One way to get those child nodes is to make a shallow copy of the fragment's childNodes before doing appendChild():

// make shallow copy, use Array.prototype to get .slice() goodness
var children = [].slice.call(frag.childNodes, 0);

element.appendChild(frag);

return children;
Crustaceous answered 12/11, 2012 at 16:17 Comment(3)
You, sir, are a freakin genius. This is quite elegant, and works perfectly in my situations. As soon as I can, barring something shockingly simpler, you will receive bounty and my undying gratitude!Dyslogia
6 years later, same exact issue. There must be a way, thinks I. Search the Googles, and alas! It is my own question! Wish I could give you another up-vote.Dyslogia
It's incredible I had to scour the internet for this solution. It's such a headscratcher, being able to append the template child just fine indicates the frag element isn't the parent template, but once you understand that it appends its childrens under the hood and its those you need to have a reference of it makes sense. BonkersHarelda
S
9

If you're looking just after appending it, the lastChild is the way to go. Use it like this:

var e = element.lastChild;

More info in SitePoint

Sewn answered 12/11, 2012 at 16:16 Comment(3)
Good thought. However, I am possibly appending this in different places, and the appended fragment could have several direct nodes it is injecting in the dom, meaning I would only get the last one of those.Dyslogia
Wow >5 years no upvotes... But this answer worked for me and I guess will in at least 50% of the situations! So easy and -> Awesome <-Effuse
In most cases element.lastElementChild would be more appropriate. Just to make sure you're getting the actual node.Lorenlorena
P
3

Like Jack's solution, but if you are using esnext you could use Array.from as

const children = Array.from(frag.children);

element.appendChild(frag);

return children;
Plainclothesman answered 3/8, 2018 at 16:46 Comment(0)
A
2

From doc of DocumentFragment:

Various other methods can take a document fragment as an argument (e.g., any Node interface methods such as appendChild and insertBefore), in which case the children of the fragment are appended or inserted, not the fragment itself.

So appendChild method return the documentFragment but it's empty because its child nodes are inserted in your element object and (from appendChild doc):

[...] a node can't be in two points of the document simultaneously. So if the node already has a parent, it is first removed, then appended at the new position.

Now... You can store in a cache array your children and after return it (or see Jack solution :-))

Archives answered 12/11, 2012 at 16:24 Comment(0)
T
0

If you have single main element in your document fragment, you can use .firstElementChild and that's all. To make multiple copies use .cloneNode(true). Example - https://codepen.io/SergeiMinaev/pen/abLzQjZ

Townswoman answered 1/12, 2021 at 18:39 Comment(0)
T
0

Thanks to @The Sloth's comment, I found this solution, which finally solved it for me:

var node = element.lastElementChild

In my case, element.lastChild returned a text node instead of the appended node.

Teachin answered 31/12, 2022 at 2:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.