Skip to content

support configurable shadowrootmode attribute for <template> tags #65

@thescientist13

Description

@thescientist13

Type of Change

  • New Feature Request

Summary

Coming out of #63 (comment), just wanted to track the discussion around how to actually support the shadowroot attribute for <template> tags as I'm not super clear on is how instances of <template> tags (HTMLTemplateElement) and ShadowRoot work together, specifically around the shadowroot="open" attribute and mode.

Specifically, as per that PR, when creating a template, a template returns its contents inside <template> tags, eg.

<wcc-footer>
  <template shadowroot="open">
    <footer class="footer">
      <h4>My Blog &copy; 2022</h4>
    </footer>
  </template>
</wcc-footer>

And when instantiating a Shadow Root in a custom element, we can set the mode that way, e.g.

class Footer extends HTMLElement {
  connectedCallback() {
    if (!this.shadowRoot) {
      this.attachShadow({ mode: 'open' });
      this.shadowRoot.appendChild(template.content.cloneNode(true));
    }
  }
}

So how does a template get access to the mode, which we would want so as to properly set the shadowroot attribute? Presumably some users may want the option of open / closed, and this may also impact how we implement #16. Also, these two are the same things, right?

Details

My understanding is shadowRoot and HTMLTemplateElement are different class hierarchies (sub classes) from what I understand, so not sure what option to pursue here? I can think of a couple options at least just to get the ball rolling

  1. User sets the attribute manually on a <template>
    const template = document.createElement('template');
    
    template.innerHTML = `    
      <footer class="footer">
        <h4>My Blog &copy; ${new Date().getFullYear()}</h4>
      </footer>
    `;
    
    template.setAttribute('shadowroot', 'open');
  2. Have the compiler check for mode when serializing and update it that way
    async function renderComponentRoots(tree) {
      for (const node of tree.childNodes) {
        if (node.tagName && node.tagName.indexOf('-') > 0) {
          ...
          
          const elementHtml = elementInstance.shadowRoot
            ? elementInstance.getInnerHTML({ includeShadowRoots: true })
            : elementInstance.innerHTML;
          const elementTree = parseFragment(elementHtml);
    
          // if we have a shadowRoot, set the `<template>` shadowroot attribute according to shadowRoot.mode
          if(elementInstance.shadowRoot) {
            const mode = elementInstance.shadowRoot.mode;
            //  do something with the tree and set the attribute on the `<template>` accordingly
          }
    
          ...
        }
    
        ...
      }
    
      return tree;
    }

I'm thinking option #2 seems pretty feasible. Also, not sure if this means we need a get innerHTML for HTMLTemplateElement too?

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions