Lightning Web Component for table rows and cells

I’m trying to build a LWC that renders a complex table-based UI. It needs to have distinct rows and columns with dynamically-determined colspans – a real table. It’s for assigning lodging, and each row will represent a room and each column for which the room can be assigned. It will involve drag/drop etc.

I was hoping to make each row and each cell a component, so that data and logic could be encapsulated in each of those. However, that doesn’t seem to work because LWC includes a tag w/ the component name in the rendered HTML.

Here’s some test code.

Table component markup:

<template>
<p>
    This is our very nice room table!
</p>
<table style="border:1px black solid">
    <!--header row goes here -->
    <template for:each={rooms} for:item="room">
        <c-ncilodgeroomtablerow key={room}>
        </c-ncilodgeroomtablerow>
    </template>
</table>
</template>

The var rooms is just set to [1,2,3] in the js controller so that it will iterate 3 times.

Here’s the row component markup, just hard-coded w/ static content for now:

<template>
<tr>
    <td>
        cell one
    </td>
    <td>
        cell two
    </td>
</tr>
</template>

This does not render as desired. It ends up with everything in one cell, because it puts c- tags around the tr tags, and I think the tr’s need to be immediate children of the table. Here’s the rendered markup:

<table style="border: 1px solid black;">
<c-ncilodgeroomtablerow>
    <tr>
        <td>cell one</td>
        <td>cell two</td>
    </tr>
</c-ncilodgeroomtablerow>
<c-ncilodgeroomtablerow>
    <tr>
        <td>cell one</td>
        <td>cell two</td>
    </tr>
</c-ncilodgeroomtablerow>
<c-ncilodgeroomtablerow>
    <tr>
        <td>cell one</td>
        <td>cell two</td>
    </tr>
</c-ncilodgeroomtablerow>
</table>

I also tried putting the trs in the table component markup, inside the iterator, and then changing the row component to just include the td tags and not the tr’s. That didn’t work either – again because of the c- tags inside the tr’s.

Is there any way to make something like this work w/ LWCs? Or do I need to look into making a css-based table layout? Open to general advice.

Answer

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;
}

Attribution
Source : Link , Question Author : mscholtz , Answer Author : tsalb

Leave a Comment