Why is `slot.assignedNodes({flatten: true})` not detecting the default `<div>` in the slot?

Viewed 518

I just spent many minutes trying to debug this issue. I found no source documenting this behavior ― maybe I missed them if they do exist ― and I decided to write this here in case someone else faces the same issue.

A Web Component I built has a <slot> element with a default <div> inside of it:

<slot name="timer">
    <div class="rp__timer"></div>
</slot>

When I tried to update the <div> using innerHTML nothing happened. It is as if the <div> doesn't exist. Here's how I tried to access the <div>:

this.timerSlot = this.shadowRoot.querySelector('slot[name=timer]');
let div = this.timerSlot.assignedNodes({flatten: true})[0];
div.innerHTML = "SOME TEXTE";

But nothing is happening. What's wrong with this code?

2 Answers

DOM nodes are not the same as DOM elements

<p>Hello<a href="">Web Components</a>World</p>

Elements p and a are a sub-set of all Nodes

So assignedNodes gives you all 5 Nodes (href in the image is an attribute)

and assignedElements gives you the 2 Elements you are after

MDN Documentation:

For documentation always use MDN (although MDN isn't 100% correct either)

So here's what's wrong with the code above.

For some reason, the <div> I created was not assigned the index 0 in the array returned by assignNodes(). It was in fact in case number one. When console.log()ed the return value of this.timerSlot.assignedNodes({flatten: true}) it came as something like this Array(3) [ #text, div.rp__timer, #text ] in both Chrome and Firefox.

It turns out the new lines I added for better readability around the <div> in the HTML file were not ignored as I believed they would.

After updating my code into a one-line configuration, i.e. <slot name="timer"><div class="rp__timer"></div></slot>, the problem disappeared and the code did what it was expected to do.

Now, I don't know it this is a feature or a bug. But since it was present in both Chrome and Firefox I assume it maybe the former. Either way, I was unable to find in the available documentation any mention of it.

I hope you'd find this useful.

Related