typescriptstenciljstsx

Building a simple table component


I would like to build two components, one for the table and one for each row.

Coding for the table looks like that:

@Component({
  tag: 'wb-overview-table',
})
export class WorkbookOverviewTable {
  items: Array<any>;

  constructor() {
    this.items = [ { id: 1, name: "asd" }, { id: 2, name: "qwes" } ];
  }

  render() {
    return (
      <table>
        {this.items.map(item => {
          return (
            <wb-overview-table-row item={item}></wb-overview-table-row>
          );
        })}
      </table>
    );
  }
}

Coding for row looks like that:

@Component({
    tag: 'wb-overview-table-row',

})
export class WorkbookOverviewTableRow {
    @Prop() item: any;

    render() {
        return (
            <tr>
                <td>{this.item.id}</td>
                <td>{this.item.name}</td>
            </tr>
        );
    }
}

The rendered html looks like that:

<wb-overview-table class="hydrated">
   <table>
      <wb-overview-table-row class="hydrated">
         <tr>
            <td>1</td>
            <td>asd</td>
         </tr>
      </wb-overview-table-row>
      <wb-overview-table-row class="hydrated">
         <tr>
            <td>2</td>
            <td>qwes</td>
         </tr>
      </wb-overview-table-row>
   </table>
</wb-overview-table>

Problem is, that the structure of the table isn't correct. And I understand why it get's rendered like that. But I just don't know how to render the table correctly, so that table-tag will have the tr-tags as child elements. What is the correct way of building two components, one for the table and one for the rows?

Thanks a lot!


Solution

  • HTML <table> elements don't allow for custom elements as children, which means you can't use a Stencil Web Component directly.

    You can, however, use a Functional component as a child row, similar to React:

    export const WorkbookOverviewTableRow = props =>
            return (
                <tr>
                    <td>{props.item.id}</td>
                    <td>{props.item.name}</td>
                </tr>
            );
        }
    }
    

    And in your table component:

      <table>
        {this.items.map(item => {
          return (
            <WorkbookOverviewTableRow item={item} />
          );
        })}
      </table>
    );
    

    These are Stencil components, but they don't get exported as Web Components, so you can only use them inside other Stencil Components.