データテーブル上に選択リストを配置してみよう!

カスタムデータタイプを使ってデータテーブル上で選択リストをインライン編集する方法について解説します。

はじめに


皆さんこんにちは!テラスカイのY.Nです。

皆さんは、LWCの開発でデータテーブルを作ったことはありますでしょうか?個人的には、データテーブルの開発は結構な頻度で必要になってくるイメージがあります。そこで使われるSalesforceの標準コンポーネントが、lightning-datatableです。

lightning-datatableは便利ですが、標準ではインライン編集できる項目が テキストや数値、日付などに限られ、選択リスト(Picklist)をそのまま編集することはできません。

本記事では、カスタムデータタイプを使ってデータテーブル上で選択リストをインライン編集する方法を解説します。最後には、応用編として 選択肢を動的に変える方法も紹介します!

標準データテーブルの限界

最初にお伝えしましたように、標準ではインライン編集できる項目が テキストや数値、日付などに限られています。試しに、標準のlightning-datatableでインライン編集が可能な選択リスト(picklist)を配置してみましょう。
// ~省略~

    columns = [
        { label: '名前', fieldName: 'Name', editable: true },
        {
            label: 'フルーツ',
            fieldName: 'Fruit__c',
            type: 'picklist',
            editable: true,
            typeAttributes: {
                // typeAttributes are supported but behavior depends on platform/version.
                // Here we list the options as an example.
                options: [
                    { label: 'りんご', value: 'apple' },
                    { label: 'みかん', value: 'orange' },
                    { label: 'いちご', value: 'strawberry' },
                    { label: 'すいか', value: 'watermelon' }
                ]
            }
        }
    ];

// ~省略~
pickListDataTable.js
このLWCを環境に配置してみると、以下のようになります。

標準選択リストのデモ

このように、標準では文字列としてしか扱われず、選択肢UIは出ません。
そのため、ユーザーは入力欄に文字列を直接打つ形になり、直感的ではありません。

解決策:カスタムデータタイプを作る

カスタムデータタイプとは・・・
lightning-datatableは、独自のLWCコンポーネントをセルに埋め込むことができます。
これを活用して、lightning-comboboxを使った選択リストを表示するカスタムセルを作ります。
Combobox · Lightning Design System 2

コード例

1.customPicklistCell

まず、各行のセルの中に <lightning-combobox> を描画するコンポーネントを作成します。
ユーザーが選択を変えたときに、イベントを発火して親コンポーネントに知らせます。
また、選択時にセルの高さをcssによって広げることで、選択肢をすべて表示させます。このcssがないと、選択肢が広がっていてもセルの高さの関係でユーザーから見えないという事態が起きてしまうためです。
<template>
  <lightning-combobox
      class="spaced-combobox"
      name="picklist"
      label={label}
      value={value}
      placeholder={placeholder}
      options={options}
      data-id={context}
      onchange={handleChange}
      onfocus={handleFocus}
      onblur={handleBlur}>
  </lightning-combobox>
</template>
customPicklistCell.html
/* lightning-comboboxの位置を微調整して見やすくする */
.spaced-combobox {
    transform: translateY(-9px);
    transition: margin 0.3s ease, transform 0.3s ease;
}

/* 編集状態のときに余白を大きくして表示崩れを防ぐ */
.spaced-combobox.editing {
    margin-bottom: 10rem;
    z-index: 1000;
    position: relative;
}
customPicklistCell.css
import { LightningElement, api } from 'lwc';
export default class customPicklistCell extends LightningElement {
    @api label;
    @api placeholder;
    @api options;
    @api value;
    @api context;

    handleChange(event) {
        const selectedEvent = new CustomEvent('picklistchange', {
            detail: {
                context: this.context,
                value: event.detail.value
            }
        });
        this.dispatchEvent(selectedEvent);
    }

    handleFocus() {
        // フォーカス時に編集モードクラスを追加
        this.template.querySelector('lightning-combobox').classList.add('editing');
    }

    handleBlur() {
        // フォーカスアウト時に編集モードクラスを削除
        this.template.querySelector('lightning-combobox').classList.remove('editing');
    }
}
customPicklistCell.js

2.customDataTable

次に、新しい列タイプを定義するコンポーネントを作成します。
先ほどから述べておりますように、Salesforce標準のlightning-datatableには "picklist" 型が存在しません。
そこでLightningDatatableを継承し、カスタムタイプに自作の型(=picklist)を追加します。
<template>
  <!-- 
    c-custom-picklist-cell コンポーネントを表示
    lightning-datatable のカスタムデータ型(picklist)用のテンプレートとして使用
  -->
  <c-custom-picklist-cell
      label={typeAttributes.label}
      value={typeAttributes.value}
      placeholder={typeAttributes.placeholder}
      options={typeAttributes.options}
      context={typeAttributes.context}>
  </c-custom-picklist-cell>
</template>
customDataTable.html
import LightningDatatable from 'lightning/datatable';
import CustomPicklistCellTemplate from './customDataTable.html';

export default class CustomDataTable extends LightningDatatable {
  /**
   * カスタムデータ型の定義
   * ここでは 'picklist' 型を定義し、カスタムテンプレートとして
   * CustomPicklistCellTemplate を使う
   */
  static customTypes = {
    picklist: {
      template: CustomPicklistCellTemplate,
      typeAttributes: ['label', 'placeholder', 'options', 'value', 'context'],
    },
  };
}
customDataTable.js

3.pickListDataTable

最後に、ユーザーに見せる「完成版のデータテーブル画面」を作成します。
<template>
    <lightning-card title="カスタムデータテーブル">
        <c-custom-data-table
            key-field="Id"
            data={data}
            columns={columns}
            hide-checkbox-column>
        </c-custom-data-table>
    </lightning-card>
</template>
pickListDataTable.html
import { LightningElement, track } from 'lwc';

export default class PickListDataTableMinimal extends LightningElement {
    @track data = [
        { Id: '1', Name: '田中太郎', Fruit__c: 'りんご' },
        { Id: '2', Name: '佐藤花子', Fruit__c: 'オレンジ' },
        { Id: '3', Name: '鈴木次郎', Fruit__c: 'いちご' }
    ];

    columns = [
        { label: '名前', fieldName: 'Name', editable: false },
        {
            label: 'フルーツ',
            fieldName: 'Fruit__c',
            type: 'picklist',  // カスタム picklist 型を使用
            typeAttributes: {
                placeholder: 'フルーツを選択',
                options: [
                    { label: 'りんご', value: 'りんご' },
                    { label: 'オレンジ', value: 'オレンジ' },
                    { label: 'いちご', value: 'いちご' },
                    { label: 'すいか', value: 'すいか' }
                ],
                value: { fieldName: 'Fruit__c' },
                context: { fieldName: 'Id' }
            }
        }
    ];
}
pickListDataTable.js

完成!

以上のコンポーネントを組み合わせることで、以下のようなデータテーブルを作成することができます!

カスタムデータテーブルのデモ

応用編:選択肢を動的に変える

これまでの方法を応用させて、同データテーブル内で選択リストの選択肢を動的に変えることができます。

今回は、それぞれの行に「やさいフラグ」というカラムを追加し、trueの場合とfalseの場合で表示される選択肢を制御してみました。

応用デモ(野菜フラグFALSE時)

応用デモ(野菜フラグTRUE時)

この制御は、行ごとの「やさいフラグ」の変更を検知し、各行ごとのピックリスト選択肢を保持するプロパティを更新、データテーブルを再描画することで可能となっています。

最後に

今回ご紹介したように、Salesforceの標準データテーブルでは選択リストのインライン編集は制限があります。しかし、カスタムデータタイプとlightning-comboboxを組み合わせることで、直感的で使いやすいインライン編集を実現できます。

さらに応用編として、行や条件に応じて選択肢を動的に変えることも可能です。これにより、単なる固定リストではなく、実務に即した柔軟なUIを作れるようになります。

標準の制約に悩むことなく、データテーブルをより便利にカスタマイズできる方法として、ぜひ参考にしてみてください。