skip to Main Content

I’m trying to figure out how to use a web component inside another web component (both of which inherit from the same base class.

The problem seems to be in the way I’m creating the shadow dom:

import BaseElement from "./base.js";

class PopupHeader extends BaseElement {
  constructor() {
    super();
  }

  async render(initial = false) {
    this.shadowRoot.innerHTML = `
        <header>
          <a href="https://example.com" id="logo" target="_blank"><img src="assets/logo.svg" alt="logo" /></a>
        </header>
      `;
  }

  async connectedCallback() {
    await this.render(true);
  }
}

customElements.define("popup-header", PopupHeader);

export default PopupHeader;

And base.js:

export default class BaseElement extends HTMLElement {
  constructor() {
    super();
    
    this.attachShadow({ mode: "open" });
  }

and main-app.js:

import BaseElement from "./base.js";

class EasyApplier extends BaseElement {
  constructor() {
    super();

    this.render = this.render.bind(this);
  }

  async render(initial = false) {
    this.shadowRoot.innerHTML = `
        <div id="${this.ns}">
          <popup-header></popup-header>
          Import profiles: <input type="file" id="json-file-input" accept="application/json" />
        </div>
      `;

  }
...
}

The issue is the header is only shown, not the rest of the main components html.

I suspect it has to do with this.shadowRoot being overridden, is there a way to avoid this?

2

Answers


  1. Just a quick glance: ${this.ns}?? You are calling this in the constructing phase??

    Can’t it be simplified to:

    class BaseElement extends HTMLElement {
      constructor( html ) {
        super().attachShadow({ mode: "open" }).innerHTML = html;
      }
    }
    
    customElements.define("popup-header", class extends BaseElement {
      constructor() {
        super(`<header>POPUP-HEADER</header>`);
      }
    });
    
    customElements.define("main-header", class extends BaseElement {
      constructor() {
        super(`<h1>MAIN-HEADER</h1><popup-header></popup-header>`);
      }
    });
    <main-header></main-header>
    Login or Signup to reply.
  2. I simplified your code for you. Don’t know why you think you needed async on render or why you sent in parameters you didn’t use.

    Moved connectedCallback() that calls render() into your BaseElement.

    Note, snippets on Stackoverflow doesn’t require exports because it’s all in the same file. You still need those if each element is in it’s own separate file, but I suggest just having export class SomeElement extends AnotherElement instead of exporting on a single row.

    The problem could be that you’re trying to import from a relative path from "./base.js" instead of an absolute path from "/base.js" (no dot).

    class BaseElement extends HTMLElement {
      constructor() {
        super();
        
        this.attachShadow({ mode: "open" });
      }
      
      connectedCallback() {
        this.render();
      }
    }
    
    // =======================
    
    // import BaseElement from "/base.js"; // from the root
    
    class PopupHeader extends BaseElement {
      render() {
        this.shadowRoot.innerHTML = `
            <header>
              <a href="https://example.com" id="logo" target="_blank"><img src="assets/logo.svg" alt="logo" /></a>
            </header>
          `;
      }
    }
    
    customElements.define("popup-header", PopupHeader);
    
    // =======================
    
    
    // import BaseElement from "/base.js";                    // from root
    // import PopupHeader from "/SUBFOLDER/popup-header.js";  // from root/SUBFOLDER
    
    class EasyApplier extends BaseElement {
      render() {
        this.shadowRoot.innerHTML = `
            <div id="${this.ns}">
              <popup-header></popup-header>
              Import profiles: <input type="file" id="json-file-input" accept="application/json" />
            </div>
          `;
    
      }
    }
    
    customElements.define("easy-applier", EasyApplier);
    <easy-applier></easy-applier>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search