WebReflection / uhtml

A micro HTML/SVG render

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Custom Element MutationObserver

lemmon opened this issue · comments

I am not sure if this is related to uhtml or I am doing someting wrong. I am trying to attach a MutationObserver to a Custom Element with shadow DOM and watch for changes in the template (outside shadow DOM, not sure what the name is for this).

html`
  <custom-element>${someValue}</custom-element>
`

I am looking to catch re-render event and apply content changes to my shadow DOM.

I am attaching [non-]working pen to illustrate my issue:
https://codepen.io/lemmonjuice/pen/rNMxxOw

When re-rendering the template nothing happens. However if I access the element directly and either change the textContent value or append a child the observer gets triggered. I was expecting that the re-render will trigger the observer as well. Checking the browser inspector I am seeing that the contetn was in fact updated properly.

Thanks.

uhtml knows nothing about ShadowDOM, so it'll keep updating the element content, not its shadow-root, which is expected (or better, it's by design, no ShadowDOM checks whatsoever as ShadowDOM has mode closed that would make it fail anyway).

However, if you instrument your observe to move within its shadowRoot nodes, everything should be fine:

      new MutationObserver((mutations) => {
        for (const {addedNodes} of mutations) {
          for (const node of addedNodes)
            this.shadowRoot.appendChild(node);
        }
      })

closing, as this is not something uhtml should solve, as it does exactly what it's expected to to 👋

Nope. I understand that uhtml doesn't access Shadow DOM, that's not my intention. As per my example:

html`
  <custom-element>${someValue}</custom-element>
`

...I am looking for changes of the someValue inside the <custom-element> tag. That element has Shadow DOM attached but changes happen within the main template whis uhtml has access to.

I think my example code works as expected already, right?

Maybe my explanation is confusing. I am not seeing the MO gets triggered on re-render.

a

...after re-rendering the template serveral times I am seeing in the inspector that inner content of the element has changed, but...

Screenshot 2020-12-03 at 18 49 53

...the observer has been triggered only on first render. No other render triggers the thing. Only accessing the element via textContent or appendChild triggers the event.

When observing attributes I am getting the result I am expecting. But not with the inner content changes.

Okay, I guess I have figured it out. I need to pass combination of options:

{
  characterData: true,
  subtree: true,
}

Thank you!

You need childList too