Lightning Web Component for table rows and cells

Building on the answer provided already by @sfdcfox, this following seems to be working for me and allows me to componentize the entire row (much easier to emit events this way).

parent.html

<table class="slds-table slds-table_bordered slds-border_left slds-border_right">
  <thead>
    <tr class="slds-line-height_reset">
      <th class="" scope="col">
        <div class="slds-truncate" title="Name">Name</div>
      </th>
      <th class="" scope="col">
        <div class="slds-truncate" title="Some Custom Column">Some Custom Column</div>
      </th>
    </tr>
  </thead>
  <tbody>
    <template for:each={iterableDataSet} for:item="row">
      <c-child-row row={row}>
      </c-child-row>
    </template>
  </tbody>
</table>

childRow.html

<template>
  <!-- taken straight from SLDS -->
  <th data-label="Name" scope="row">
    <div class="slds-truncate" title={row.Name}>{row.Name}</div>
  </th>
  <td data-label="Some Custom Column">
    <div class="slds-truncate">
      <lightning-input
        data-id={row.Id}
        type="number"
        variant="label-hidden"
        name="inputForDataField"
        onchange={handleOnChange}
        value={row.Data_Field__c}>
      </lightning-input>
    </div>
  </td>
  <!-- more tds .... -->
</template>

And the critical piece on childRow.css

:host {
  display: table-row;
}

Ideally, you shouldn't use table; lightning-layout and lightning-layout-item work as tables for all practical purposes. If that doesn't work for you, then you'd want to simply apply the appropriate CSS to your components.

Row Display

:host {
  display: table-row;
}

Cell Display

:host {
  display: table-cell;
}

I seem to be having a problem writing a working version of this, but it should work once everything is nested. Do not include tr in your row component, nor td in your cell component. Your component becomes the row/cell, so you don't need to nest them.


I agree with most statements from the comments where there are better choices than a table but another option I found is to use the following CSS in your "row" component:

:host{
    display: contents;
}

This causes an element's children to appear as if they were direct children of the element's parent, ignoring the element itself.

Do note that browser support still has some issues.

https://caniuse.com/#search=display%3A%20contents

Specifically in the accessibility area (people using assistive technology). You can read about that here:

https://hiddedevries.nl/en/blog/2018-04-21-more-accessible-markup-with-display-contents

So if accessibility would be a criteria for your components, keep this in mind.