<table> child elements usage in shadow dom

Viewed 686

Is there any constraint that's preventing <thead>, <tbody>, <tr> and so on to be slotted in shadow DOM?

Given the following example:

<script>
class Table extends HTMLElement {
    constructor() {
        super();
        this.attachShadow({mode: 'open'}).innerHTML = `
            <table>
                <thead>
                    <slot name="header"></slot>
                </thead>
                <tbody>
                    <slot name="row"></slot>
                </tbody>
            </table>
        `;
    }
}
window.customElements.define('data-table', Table);
</script>
<data-table>
    <tr slot="header">
        <th>header1</th>
    </tr>
    <tr slot="row">
        <td>cell1</tr>
    </tr>
</data-table>

renders into the following structure:
enter image description here

The workaround would be to use templates and insert template content with JS in slotchange event handler, but I would like to avoid that since the cloned content would end up in shadow DOM and it will not be possible to override styles from outside of the custom element.

2 Answers

As stated in the comment this is currently not possible according to Custom Elements spec v1.
The spec limits tags of <table> to a set of <tbody>, <thead> and so on plus <script> and <template>.
Browser vendors are reluctant to incorporating changes in their HTML parser https://github.com/WICG/webcomponents/issues/59.
Guess the only solution for now is to use a mesh of divs with a bunch of aria-* attributes.

put other tags on the table it's not correct then you should use css prop ( display: table-cell;, display: table-row, display: table-header-group;, display: table-footer-group;) with other tags.

But if you still want to use the table,

you can append tag with function as follow:

lit playground

import {html, css, LitElement} from 'lit';
import {customElement, property} from 'lit/decorators.js';

@customElement('data-table')
export class dataTable extends LitElement {
  static styles = css`
      table {
       border:1px solid;
      }
  `;
  render() {
    return html`
     <table>
        ${this.templateGen()}
     </table>
    `;
  }
  
  
  templateGen() {
   return html`<slot></slot>`;
  }
}
<!DOCTYPE html>
<head>
  <script type="module" src="./simple-greeting.js"></script>
</head>
<body>
  <data-table><p>Test slot in table<p></data-table>
</body>
Related