lightning-datatableを使用して、保存ボタン押下せず、インライン編集で即時データ保存できる方法を紹介するよ!
ユーザビリティ意識すると、今のご時世「保存」ボタン押下しないで直接更新させたいよね!
というわけで、今回は、取引先レコード詳細ページに配置するLWCを紹介するよ!
内容は、取引先に紐付いている取引先責任者一覧をリストで表示し、インライン編集して即時データ更新・保存するよ!
また、名前はリンクになっていて、ページ遷移も出来るよ!
以下、まずはサンプルコードだよ!VSCodeで作成してね!
ContactController.cls
public with sharing class ContactController {
@AuraEnabled(cacheable=true)
public static List<Contact> getContactsByAccount(Id accountId) {
// 引数が空なら空リストを返す
if (String.isBlank(accountId)) {
return new List<Contact>();
}
return [
SELECT Id, Name, Title, Phone, Email
FROM Contact
WHERE AccountId = :accountId
ORDER BY CreatedDate DESC
];
}
@AuraEnabled
public static void updateContacts(List<Contact> updatedContacts) {
if (updatedContacts == null || updatedContacts.isEmpty()) {
return;
}
update updatedContacts;
}
}
inline.html
<template>
<lightning-card title="取引先責任者">
<div class="hide-buttons">
<lightning-datatable
key-field="Id"
data={contacts}
columns={columns}
draft-values={draftValues}
editable
oncellchange={handleCellChange}
hide-checkbox-column
suppress-bottom-bar
>
</lightning-datatable>
</div>
</lightning-card>
</template>
inline.js
import { LightningElement, api, track, wire } from 'lwc';
import getContactsByAccount from '@salesforce/apex/ContactController.getContactsByAccount';
import updateContacts from '@salesforce/apex/ContactController.updateContacts';
import { refreshApex } from '@salesforce/apex';
export default class AutoSaveContacts extends LightningElement {
@api recordId;
@track contacts = [];
@track draftValues = [];
wiredResult;
// データテーブル列定義
columns = [
{
label: '氏名',
fieldName: 'NameUrl', // 実際のリンク先URL
type: 'url',
typeAttributes: {
label: { fieldName: 'Name' }, // 表示する文字列
target: '_self', // 新規タブを開く場合は '_blank'
tooltip: { fieldName: 'Name' }
},
editable: false
},
{
label: '役職',
fieldName: 'Title',
type: 'text',
editable: true
},
{
label: '電話',
fieldName: 'Phone',
type: 'phone',
editable: true
},
{
label: 'メールアドレス',
fieldName: 'Email',
type: 'email',
editable: true
}
];
// 取引先責任者を取得
@wire(getContactsByAccount, { accountId: '$recordId' })
wiredContacts(result) {
this.wiredResult = result;
const { data, error } = result;
if (data) {
// データにリンク先URLを付与
this.contacts = data.map(contact => ({
...contact,
NameUrl: `/lightning/r/Contact/${contact.Id}/view`
}));
} else if (error) {
console.error('取引先責任者取得エラー: ', error);
}
}
// セル変更時の保存処理
handleCellChange(event) {
const changedValues = event.detail.draftValues;
updateContacts({ updatedContacts: changedValues })
.then(() => {
// Apex更新成功後、最新データにリフレッシュ
return refreshApex(this.wiredResult);
})
.then(() => {
// 保存後、draftValuesをクリアして編集モードをリセット
this.draftValues = [];
})
.catch(error => {
console.error('更新エラー: ', error);
});
}
}
inline.css
.hide-buttons .slds-cell-edit__button,
.hide-buttons .slds-button.slds-button_icon.slds-button_icon-border-filled {
display: none !important;
}
inline.xml
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>62.0</apiVersion>
<isExposed>true</isExposed>
<targets>
<target>lightning__RecordPage</target>
</targets>
</LightningComponentBundle>
VSCodeを使用した作成手順
1.ContactController.clsを作成、デプロイ2.inline.js、html、css、xmlを作成、デプロイ
全体の流れ
- 取得結果は wiredContacts(result) の result に渡される。
- その結果を this.contacts に代入し、画面の lightning-datatable に表示される。
- event.detail.draftValues に編集された項目と値が格納される。
- 更新成功後に .then() 内の処理が継続。
- これにより最新の取引先責任者情報を再取得し、画面へ反映。
JavaScriptのポイント
- ユーザーがセルを編集すると、自動的に event.detail.draftValues に編集されたフィールドや値が配列形式で入る。
- そこで refreshApex() を利用し、最初に登録した this.wiredResult(@wireの戻り値)を再取得する。
- 再取得成功後、ユーザーが見ているデータテーブルにも最新のContact情報が映る
- これで編集途中の状態をクリアして、また新たに編集できるようにする。
※2、3がないと最新データでの画面描画がされないんだよね!
HTMLのポイント
lightning-datatable がテーブルの行を認識するために必要で、"Id" フィールドを使うのが一般的です。
ユーザーがセルを編集すると、その変更内容は自動的に {draftValues} に反映されます。
Apex保存後などのタイミングでクリアしてあげることで、編集モードをリセットできます。
これを指定することで、テーブルのセルをクリックした時に編集が可能になります。
非表示にすることで、ユーザーは編集したら自動的に保存処理(または独自の保存処理)が行われるようなUIにできます。
※保存時に一瞬保存ボタンが見えてしまうので、そこはcssを使用して無理矢理非表示にしているよ!
今回はサンプルコード&インラインが本題だから、強引なやり方だよ!
インライン編集で保存ボタン使用せず保存することは、ユーザビリティ向上になるよね!
何か参考になれば嬉しいな!
今後も初心者~中級者向けにどんどんアップしていくので、フォロー&いいねよろしくね!!!