'createTHead' called on an object that does not implement interface HTMLTableElement

Viewed 40

I am trying to create a custom Web Component that extends the HTMLTableElement class. The code is relatively simple:

class DataTable extends HTMLTableElement {
    constructor() {
        super();
        this.data = JSON.parse(decodeURIComponent(this.getAttribute(data)));
        const head = this.createTHead();
    }
}

customElements.define('data-table', DataTable, {extends:'table'});

The error comes when I try to call createTHead(). According to documentation, this is a function of HTMLTableElement (which my class extends) and returns an HTMLTableSectionElement object. However, I get an error as stated in the title: createTHead called on an object that does not implement interface HTMLTableElement

I am expecting the HTMLTableSectionElement to be created, instead I get the error. I have tried to remove the options from the define call, and I get an "Illegal Constructor" error.

Reproducible: https://jsfiddle.net/nw3rsjtv/

1 Answers

When extending built-in elements, you don't use it with your own tag name.

That is why your current code is giving you

Uncaught TypeError: Illegal constructor: autonomous custom elements must extend HTMLElement 

Instead, you provide your registered component name in an is-attribute:

Change

<data-table data="..."></data-table>

to

<table is="data-table" data="..."></table>

Open this in a browser: https://codepen.io/connexo/pen/OJZRbmO

class DataTable extends HTMLTableElement {
  constructor() {
    super();

    this.data = JSON.parse(decodeURIComponent(this.getAttribute("data")));
    if (!Array.isArray(this.data)) {
      console.error("data attribute expects an array of objects.");
    }

    const head = this.createTHead();
    for (let k of Object.keys(this.data[0])) {
      console.log(k);
    }
  }
}

customElements.define("data-table", DataTable, { extends: "table" });
<!-- Polyfill for browsers that do not support the full web component spec -->
<script src="https://cdn.jsdelivr.net/npm/@ungap/custom-elements@1.1.0/min.js"></script>

<table is="data-table" data="%5B%7B%22header1%22:1,%22header2%22:2%7D%5D"></table>

Related