💭

LWCでテーブルの行コンポーネントがうまく表示されなかったので、display:table-row;した

2021/05/03に公開

LWCでDatatableを作るには lightning-datatable が利用できますが、HTML と Salesforce の Lightning Design System を使えばスクラッチでもそれっぽく作成する事ができます。簡単に出来るだろうと思って作ってみたら意外なところでハマったので、今回はトラブルシューティングな小ネタです。

行コンポーネントがうまく表示されない

サンプルとして CustomDatatable という自作のデータテーブルから、行コンポーネントである Tr を呼び出しています。テーブルで表示するデータは例のごとくサンプルデータのハードコードです。

customDatatable.html
  <table class="slds-table slds-table_cell-buffer slds-table_bordered">
    <thead>
      <tr class="slds-line-height_reset">
        <template for:each={headers} for:item="header">
          <th key={header.key} scope="col">
            <div class="slds-truncate">{header.label}</div>
          </th>
        </template>
      </tr>
    </thead>
    <tbody>
      <template for:each={records} for:item="record">
        <c-tr key={record.id} class="slds-hint-parent" record={record}></c-tr>
      </template>
    </tbody>
  </table>
customDatatable,js
import { LightningElement } from "lwc";
const headers = [
  { label: "氏名", key: "name" },
  { label: "生年月日", key: "birthdate" }
];
const records = [
  {
    id: "001",
    name: "林恵美",
    birthdate: "1980/01/01"
  }
];
export default class CustomDatatable extends LightningElement {
  headers = headers;
  records = records;
}

そして、Tr コンポーネントの実装はこちらです。CustomDatatableから受け取ったrecordを行として描画しています。

tr.html
<template>
  <tr>
    <th scope="row">
      <div class="slds-truncate">{record.name}</div>
    </th>
    <td>
      <div class="slds-truncate">{record.birthdate}</div>
    </td>
  </tr>
</template>
tr.js
import { LightningElement, api } from "lwc";
export default class Tr extends LightningElement {
  @api record;
}

一見なんの問題も内容にみえます(少なくとも当時の私にはそう見えていました)が、このコンポーネントを実際に表示してみると表示が崩れています。

display:table-row;で対応する

生成されたHTMLを確認すると分かりますが、tbodytrの間に行コンポーネントであるc-trタグが入っているのでtableの構造体ではなくなっているのが原因です。

対応策としてはc-trtrとして認識させればいいので、まずtr.htmlからtrタグを削除します。

tr.html
<template>
  <th scope="row">
    <div class="slds-truncate">{record.name}</div>
  </th>
  <td>
    <div class="slds-truncate">{record.birthdate}</div>
  </td>
</template>

そして、c-trタグをtrとして認識させるために、tr.cssを作成して:hostセレクタにdisplay: table-row;を追加します。

tr.css
:host {
  display: table-row;
}
:host > th:first-child {
  padding-left: var(--lwc-spacingLarge, 1.5rem);
}

(ちゃっかり左パディングも追加😏)

これで想定通り表示されるようになりました。

参考

Discussion