Trying to adhere to the DRY principal, I wanted to create a custom component based on a <template>. The code looked something like this (please forgive the corner-cutting as I'm typing this on a phone after an all-nighter):
// base.html
<template id="player">
  <div class="card">
    <div class="card-body">
      <slot name="user-username"></slot>
    </div>
  </div>
</template>
// app.js
class PlayerCard extends HTMLElement {  
  constructor(){
    super();
    let tmpl = querySelector...;
    this.appendChild(tmpl.content.cloneNode();
  }
}
define('player-card', PlayerCard);
// index.html
{% for user in users %}
  <player-card>
    <div slot="user-username">{{ user }}</div>
  </player-card>
{% end for %}
But after smashed dreams and long hours of research, I learned that slots can only be used in Shadow DOMs. The problem with using SDOM is that the internal styling is protected and can't be directly influenced by the external CSS.
This means that, at one hand, i can't inject the data to the template instance, nor can I use Shadow DOM without having to reimplement Bootstrap.
And I'm stuck. To my brain, there must be a way to make this work but my brain is unable to find it — either because it's too complex, or it's too trivial and easy.
Any suggestions please?
Yes, <SLOT>s can only be used inside shadowDOM
But you can do a lot more with styling slots.
For long answer see: ::slotted CSS selector for nested children in shadowDOM slot
customElements.define('player-card', class extends HTMLElement {
    constructor() {
      let template = (id) => document.getElementById(id).content.cloneNode(true);
      super()
         .attachShadow({mode: 'open'})
         .append(template(this.nodeName));
      this.onclick = (evt) => this.style.color='blue';
    }
});/* GLOBAL CSS */
player-card { /* inheritable styles trickle down into shadowDOM */
  font: 20px Arial;
  color: green;
}
[slot="username"] { /* lightDOM styles are REFLECTED to SLOTs */
  width: 200px;
  border: 2px solid green;
}<template id="PLAYER-CARD">
  <style shadowDOM-CSS > 
    div { /* styles do not style content in SLOTs */
      padding: 1em;
      background:gold;
    }
    ::slotted(*) { /* slotted can only style the lightDOM 'skin' */
      background: lightgreen;
    }
  </style>
  <div>
    <slot name="username"></slot>
  </div>
</template>
<player-card>
    <!-- lightDOM, hidden when shadowDOM is used, then REFLECTED to SLOT -->
    <div slot="username">Ahmed</div>
</player-card>
<player-card>
    <!-- lightDOM, hidden when shadowDOM is used, then REFLECTED to SLOT -->
    <div slot="username">Danny</div>
</player-card>If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With