【LWC】Datatableにボタンを配置する
はじめに
LWC(Lightning Web Component)でDatatableにボタンを配置しました。非活性化したり、色を変えたりできます。
完成形
実装方法
コード
HTML
<template>
<lightning-card title="取引先一覧">
<div class="slds-card__body slds-card__body_inner">
<lightning-datatable
key-field="Id"
data={accounts}
columns={columns}
onrowaction={handleRowAction}
hide-checkbox-column>
</lightning-datatable>
<lightning-input
value={inputText}
variant="label-hidden"
readonly>
</lightning-input>
</div>
</lightning-card>
</template>
JavaScript
import { LightningElement } from 'lwc';
const columns = [
{ label: '取引先名', fieldName: 'Name' },
{ label: 'Webサイト', fieldName: 'Website', type: 'url' },
{
type: 'button',
typeAttributes: {
label: { fieldName: 'buttonLabel' },
name: 'showText',
disabled: { fieldName: 'isOpened' }
},
cellAttributes: { alignment: 'center' },
fixedWidth: 100
},
{
type: 'button-icon',
typeAttributes: {
iconName: 'utility:heart',
variant: 'container',
name: 'toggleFavorite',
},
cellAttributes: {
alignment: 'center',
class: { fieldName: 'buttonFormat' }
},
fixedWidth: 50
}
];
export default class Datatable extends LightningElement {
accounts = [];
columns = columns;
inputText;
connectedCallback() {
this.accounts = this.prepareTableData().map(row => ({
...row,
buttonLabel: '表示',
isOpened: false,
isFavorite: false,
buttonFormat: 'slds-icon-text-light'
}));
}
prepareTableData() {
return [
{
Id: 'xxxxxxxxxxxxxxx',
Name: 'xxx株式会社',
Website: 'https://xxx-example.com'
},
{
Id: 'yyyyyyyyyyyyyyy',
Name: 'yyy株式会社',
Website: 'https://yyy-example.com'
},
{
Id: 'zzzzzzzzzzzzzzz',
Name: 'zzz株式会社',
Website: 'https://zzz-example.com'
}
];
}
handleRowAction(event) {
const actionName = event.detail.action.name;
const row = event.detail.row;
switch (actionName) {
case 'showText':
this.showText(row);
break;
case 'toggleFavorite':
this.toggleFavorite(row);
break;
default:
break;
}
}
showText(selectedAccount) {
// 選択されたかどうかを判定する
const isSelected = (Id) => {
return Id === selectedAccount.Id;
};
// ボタンのラベルと活性状態を変更
this.accounts = this.accounts.map(account => ({
...account,
buttonLabel: isSelected(account.Id) ? '表示中' : '表示',
isOpened: isSelected(account.Id)
}));
this.inputText = `表示中:${selectedAccount.Name}`;
}
toggleFavorite(selectedAccount) {
// 反転
selectedAccount.isFavorite = !selectedAccount.isFavorite;
// ボタンの色を変更
if (selectedAccount.isFavorite) {
selectedAccount.buttonFormat = 'slds-icon-text-error';
} else {
selectedAccount.buttonFormat = 'slds-icon-text-light';
}
this.accounts = this.accounts.map(account => {
if (account.Id === selectedAccount.Id) {
return selectedAccount;
}
return account;
});
this.removeFocus();
}
// 強制的にフォーカスを外す
removeFocus() {
this.template.querySelector('lightning-input').focus();
this.template.querySelector('lightning-input').blur();
}
}
解説
Datatableにボタンを配置する
Datatableのカラム設定時、type
プロパティにbutton
(アイコンのみのボタンの場合はbutton-icon
)を指定すると、そのカラムがボタンだと認識されます。
ボタンに表示したいテキストは、typeAttributes
プロパティのlabel
に指定します。
ボタンにアクションを追加する
配置したボタンをクリックしたときにアクションを実行(レコードページを開く、レコードを削除する、表示を変えるなど)したい場合、HTMLのonrowaction
にイベントハンドラを指定する必要があります。
handleRowAction(event) {
const actionName = event.detail.action.name;
const row = event.detail.row;
switch (actionName) {
case 'showText':
this.showText(row);
break;
case 'toggleFavorite':
this.toggleFavorite(row);
break;
default:
break;
}
}
上記のように、引数のevent.detail.action.name
にtypeAttributes
プロパティのname
が対応しており、event.detail.row
にクリックしたボタンが存在する行のデータが保持されます。
このコードでは、アクションごとに別のメソッドを呼び出し、各アクションを実行しています。
アクション実行時にボタンの見た目を変える
もしDatatableに表示しているデータを変更したい場合、
this.accounts[index].Name = 'new株式会社';
のように、変更したいプロパティ(この場合はName
)に新しい値を代入すると思います。
これでなぜ表示が変わるかというと、Datatableのカラム設定時にfieldName
としてName
を指定しているからです。
これと同じことがボタンでも可能です。
const columns = [
...
{
type: 'button',
typeAttributes: {
label: { fieldName: 'buttonLabel' },
name: 'showText',
disabled: { fieldName: 'isOpened' }
},
...
},
{
type: 'button-icon',
...
cellAttributes: {
...
class: { fieldName: 'buttonFormat' }
},
...
}
];
上記のように、変更可能な値をカラムに設定するときにfieldName
プロパティを使用します。
あとはDatatableのデータに同一名のプロパティを設定し、アクションに応じて値を代入すればそれぞれボタンの見た目が変わります。
今回取り上げたのは、以下の3つです。
- ボタンのラベル
- ボタンの活性・非活性
- ボタンのCSSクラス
これらを使いこなせれば、UI的に使い勝手のいいLWCが実装できると思います。
参考
終わりに
これは個人的に実務でもよく使います。ドキュメントがもう少し揃っているとうれしいですね。
Discussion