Search code examples
javascripthtmlpolymerweb-componentstenciljs

Nesting web components and mixing it with regular HTML


Is it possible to create independent web components with Stencil or Polymer and then nest them one within another? Also, is it possible to mix all of that with regular HTML content?

We would have 3 independent components here, with unique styles and functionalities.

  • <comp-card>
  • <comp-avatar>
  • <comp-text-box>

They should be nested inside of regular HTML like this for example:

<comp-card>
    <comp-avatar>
        <img src="...">
    </comp-avatar>
    <comp-text-box>
        <p>lorem ipsum</p>
    </comp-text-box>
</comp-card>

Is this possible to achieve this today with native web components?


Solution

  • I'm not sure about native web components but it definitely is possible within polymer. For instance my main polymer app file contains:

    <module-landing>
      <firebase-content path="pages/home/tagline"></firebase-content>
    </module-landing>
    

    and within my custom module-landing there is:

      <template>
    
    <style>
       ...
    </style>
    
    
    <module-inner size="1140px">
        <h1 id="title">
          <slot></slot>
        </h1>
        <img id="goDown" class="icon" src="" on-click="raiseCurtain">
    </module-inner>
    
    </template>
    
    
    <script>
    /**
     * `module-landing`
     * Full screen landing element with an arrow that scrolls itself out of the way, content is loaded through Firebase (requires firebase to be initialised in main app)
     *
     * @customElement
     * @polymer
     * @demo demo/index.html
     */
    class ModuleLanding extends Polymer.Element {
      static get is() { return 'module-landing'; }
      static get properties() {
        return {
          height: {
            type: Number
          }
        };
      }
      ready(){
        super.ready();
        this.height = this.offsetHeight;
        this.$.goDown.src = this.resolveUrl("assets/white-down-arrow.png");
      }
    
      raiseCurtain(){
        window.scroll({ top: this.height, left: 0, behavior: 'smooth' });        
      }
    
    }
    
    window.customElements.define(ModuleLanding.is, ModuleLanding);
    

    (note the slot tags indicating where content nested within the custom element in the main file should appear, and the module-inner custom element inserted within the landing).