4

Caveat When Using Umbrella JS With Template Elements In JavaScript

 1 year ago
source link: https://www.bennadel.com/blog/4263-caveat-when-using-umbrella-js-with-template-elements-in-javascript.htm
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Caveat When Using Umbrella JS With Template Elements In JavaScript

By Ben Nadel on May 9, 2022

The other day, when generating PDF document signatures with html2canvas, I was using a <template> element to stamp-out DOM-element clones within my JavaScript application. Those clones were each subsequently wrapped in an Umbrella JS instance for easy DOM-manipulation. However, I ran into some quirkiness if I tried to .appendTo() the clone to the document body before I was done manipulating it. It seemed that none of the API calls that I was making to the Umbrella JS instance were being applied to the clone once the template clone was rendered to the DOM.

Run this demo in my JavaScript Demos project on GitHub.

View this code in my JavaScript Demos project on GitHub.

To be honest, it's been a looong time since I've worked directly with a DocumentFragment. Most of my work these days is done in AngularJS and Angular, which provides HTML directives that, more or less, obviate the need for DocumentFragment usage. As such, the rules around fragments have slowly left my head.

When I was working on the demo the other day, I was thinking about a fragment like it was a collection of arbitrary references. Somewhat akin to an Array of DOM elements. But, that's not what it is at all - it's a light-weight DOM tree. This is a critical distinction because any given DOM node can only exist in one place within a DOM tree at one time. As such, by adding the contents of a fragment to the body, we are implicitly removing the contents from the fragment.

Again, any given DOM node can only exist in one part of the DOM at a time.

This behavior is explicitly outlined in the DocumentFragment documentation on MDN:

A common use for DocumentFragment is to create one, assemble a DOM subtree within it, then append or insert the fragment into the DOM using Node interface methods such as appendChild() or insertBefore(). Doing this moves the fragment's nodes into the DOM, leaving behind an empty DocumentFragment.

And, this is exactly what was happening to me. Only, since I was using Umbrella JS to access the DOM, it wasn't immediately clear to me that the fragment was suddenly empty. That's because an Umbrella JS instance - like a jQuery instance - will happily work with an empty collection, turning all API methods into no-ops.

Let's see this behavior in action. In the following JavaScript code, I'm going to clone a <template> and then inject it into the DOM. It contains a single paragraph tag; and, I'm going to try to adjust the textContent both before and after the injection:

As you can see, I'm wrapping the fragment in an Umbrella JS instance. Then, I'm using the .find() methods to try and locate the embedded paragraph tag. And, when we run this in the browser, we get the following output:

Document showing text that was applied prior to DOM node injection.

Notice that the rendered DOM only shows the "Before appending" text, not the "After appending" text. That's because the Umbrella JS wrapper for the fragment was emptied out the moment I appended the fragment to the body element. As such, the call to:

clone.find( "p" )

... resulted in an empty Umbrella JS collection, which happily turned the .text() call:

.text( "After appending to body." )

... into a silent no-op.

This only happens because I was re-finding the p tag via the fragment wrapper. If I had stored a reference to the p tag directly, this code would have worked as expected.

To be clear, none of this is a bug. Both Umbrella JS and the DocumentFragment are working just as they are documented. The only error here was in my mental model for how fragments work; and, how they change once injected into the rendered DOM. I'm only writing this up as a means to pound it into my head.

Enjoyed This Post? ❤️ Share the Love With Your Friends! ❤️

Tweet This Interesting post by @BenNadel - Caveat When Using Umbrella JS With Template Elements In JavaScript

Reader Comments

What has two thumbs and hopes you leave a comment? This Guy! (Ben Nadel).

Post A Comment — ❤️ I'd Love To Hear From You! ❤️

Name:

Email:

Website:

Comment:
NEW: Some basic markdown formatting is now supported: bold, italic, blockquotes, lists, fenced code-blocks. Read more about markdown syntax »
Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.

Subscribe to comments.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK