Home > Enterprise >  Javascript Web-Components - add subitems
Javascript Web-Components - add subitems

Time:05-02

class Table extends HTMLElement {
  // attributes
  constructor() {
    super();
    this.name = 'undefined';
    this.icon = 'bi-patch-question';
  }

  // component attributes
  static get observedAttributes() {
    return ['name', 'icon', 'properties'];
  }

  // attribute change
  attributeChangedCallback(property, oldValue, newValue) {
    if (oldValue == newValue) return;
    this[ property ] = newValue;
  }

  connectedCallback() {
    const shadow = this.attachShadow({ mode: 'open' });

    shadow.innerHTML = `
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.css">
    <div >
    <table >
      <tr>
          <caption>${this.name}<i ></i></caption>
      </tr>
      <!-- here should be the em-tds -->
    </table></div>
    
    <style>
    .card {
      border: 1px solid lightgray;
      border-radius: 15px;
      margin: 10px 0;
      padding: 15px;
    }
  
    table {
        width: 100%;
        border-collapse: collapse;
    }

    tr {
      border-top: 1px solid lightgrey;
    }

    tr:first-child {
      border: none;
    }

    td {
      width: 100%;
      padding: 7px;
      font-size: 18px;
      vertical-align: middle;
    }

    caption {
        position: relative;
        font-family: ExtraBold;
        padding: 7px;
        margin-bottom: 5px;
        text-align: left;
        font-size: 18px;
        text-decoration: 2px underline;
    }

    caption i {
      position: absolute;
      right: 6px;
      font-size: 22px;
    }
    </style>
    `
  }
}

class TableTds extends HTMLElement {
  // attributes
  constructor() {
    super();
    this.name = 'undefined';
    this.value = 'undefined';
  }

  // component attributes
  static get observedAttributes() {
    return ['name', 'value'];
  }

  // attribute change
  attributeChangedCallback(property, oldValue, newValue) {
    if (oldValue == newValue) return;
    this[ property ] = newValue;
  }

  connectedCallback() {
    const shadow = this.attachShadow({ mode: 'open' });

    shadow.innerHTML = `
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.css">
    <td>${this.name}</td>
    <td>${this.value}></td>
    `
  }
}




customElements.define('em-table', Table);
customElements.define('em-td', TableTds);
<em-table name="test">
  <em-td name="test" value="10"></em-td>
  <em-td name="test" value="10"></em-td>
</em-table>

I'm working on new web-components for my plattform and ran in some kind of issue. Creating web-components works fine for me but I wanted to create sub-components inside the tags of a web-component. Obviously that has not worked, because the component is protected from everything else...

In my case its about a table web-component, in which I would like to have the html-tds as subcomponents, to later use them properly.

I've tried to use slots but that has not worked...

CodePudding user response:

This should get you started, you need to add more yourself.

Main point is not to wrap Everything in a shadowDOM,
let your em-td find their "table", without having to pierce UP through a shadowroot boundary
with:

    connectedCallback() {
      this.closest("em-table")
          .shadowRoot
          .querySelector("table")
          .append(this.tr);
    }
Working snippet:

Note: using a declarative shadowDOM <template shadowroot="open"> for em-table here.
You can move it all to its constructor if you don't want to start from SSR/HTML

<em-table name="test">
  <template shadowroot="open">
    <div >
      <table >
        <caption></caption>
      </table>
    </div>
    <style>
      tr{background:pink}
    </style>
  </template>
  <em-td name="test1" value="10"></em-td>
  <em-td name="test2" value="20"></em-td>
</em-table>
<script>
  customElements.define('em-table', class extends HTMLElement {
    caption(name, icon) {
      let html = `${name}<i ></i>`;
      this.shadowRoot.querySelector("caption").innerHTML = html;
    }
    connectedCallback() {
      this.caption('caption', 'bi-patch-question');
    }
    static get observedAttributes() {
      return ['name', 'icon', 'properties'];
    }
    attributeChangedCallback(property, oldValue, newValue) {
      if (oldValue == newValue) return;
      this[property] = newValue;
    }
  });
  customElements.define('em-td', class extends HTMLElement {
    static get observedAttributes() {
      return ['name', 'value'];
    }
    constructor() {
      super();
      this.tr = document.createElement("tr");
      this._name = document.createElement("td");
      this._value = document.createElement("td");
      this.tr.append(this._name, this._value);
    }
    attributeChangedCallback(property, oldValue, newValue) {
      if (oldValue == newValue) return;
      this[property] = newValue;
    }
    set name(v) {
      this._name.innerText = v;
    }
    set value(v) {
      this._value.innerText = v;
    }
    connectedCallback() {
      this.closest("em-table")
          .shadowRoot.querySelector("table")
          .append(this.tr);
    }
  });
</script>

And be aware:

From the <TR> documentation on MDN:

https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tr

Permitted parents

<table> (only if the table has no child <tbody> element, and even then only after any <caption>, <colgroup>, and <thead> elements); otherwise, the parent must be <thead>, <tbody> or <tfoot>

So

<em-table>
  <tr>

is not valid HTML

  • Related