LWC(Lightning Web Components)で画面開発が必要なケースとして、標準UIだけでは実現できない動的な操作やリアルタイム更新が求められる場面を挙げます。
具体的な事例を5つ紹介し、それぞれの要件とLWC実装の概要を記載します。
LWCが必要なケース(標準UIでは対応困難なもの)
1. 商談の見積明細を動的に追加・削除できるカスタムUI
要件
-
Opportunity
のレコードページに、関連するQuoteLineItem
を表示。 - 行を追加・削除できるインタラクティブなUIを提供。
- 計算結果(合計金額など)をリアルタイム更新。
LWC実装の概要
-
lightning-datatable
を使用して見積明細を表示。 - ボタン操作で行の追加・削除を可能にする。
-
@track
を使い、合計金額などの計算値を即時更新。 -
Apex
でデータの取得・保存を処理。
2. リアルタイム在庫チェックと注文処理
要件
-
Product
オブジェクトの在庫数をリアルタイムで取得。 -
OpportunityLineItem
追加時に、在庫が不足していれば警告を表示。 - WebSocket や Platform Events を利用し、他ユーザーの変更を即時反映。
LWC実装の概要
-
@wire
を使ってApexから在庫データを取得。 -
lightning-input
で注文数を入力し、在庫と比較。 - 在庫不足時は
lightning-toast
でアラート表示。 - Platform Events を購読し、他ユーザーの更新を反映。
3. 商談の進捗をガントチャートで可視化
要件
-
Opportunity
の各フェーズをガントチャートで表示。 - ドラッグ&ドロップでフェーズを変更可能。
- 変更内容は即座にSalesforceへ保存。
LWC実装の概要
-
third-party JavaScriptライブラリ(D3.js, Chart.js)
を活用。 -
lightning-record-edit-form
を利用してドラッグ&ドロップ後にデータ更新。 -
@wire
で商談フェーズのデータを取得・更新。
4. ユーザーがファイルをドラッグ&ドロップでアップロードし、プレビュー
要件
-
Case
(問い合わせ)にファイルを添付する際、ドラッグ&ドロップでアップロード可能にする。 - アップロード前に画像プレビューを表示。
- PDFや画像ファイルの内容をプレビュー可能。
LWC実装の概要
-
lightning-file-upload
を使用。 -
onchange
イベントでファイルを一時保存し、プレビュー表示。 -
ContentDocumentLink
を利用し、ファイルをCase
に関連付け。
5. 顧客検索&即時編集可能なカスタム検索コンポーネント
要件
-
Account
を検索できるコンポーネントを作成。 - 部分一致検索が可能(標準の
lookup
では難しい)。 - 検索結果をクリックすると、その場で編集&保存。
LWC実装の概要
-
lightning-input
で検索キーワードを入力。 -
@wire
を使用し、ApexでLIKE
検索を実施。 -
lightning-datatable
に結果を表示し、inline editing
を有効化。
まずは 「商談の見積明細を動的に追加・削除できるカスタムUI」 の実装例を示します。
このLWCコンポーネントは、Opportunity
のレコードページに配置し、QuoteLineItem
(見積明細)の追加・削除、合計金額のリアルタイム更新ができるようにします。
1. 商談の見積明細を動的に追加・削除できるカスタムUI
実装概要
- 見積明細(QuoteLineItem)を
lightning-datatable
で表示 - ユーザーが行を追加・削除可能
- 合計金額をリアルタイムで計算
- SalesforceデータをApex経由で取得・更新
1.1 Apexクラス
LWC から Opportunity
の QuoteLineItem
データを取得・更新する Apex クラスを作成します。
public with sharing class QuoteLineItemController {
@AuraEnabled(cacheable=true)
public static List<QuoteLineItem> getQuoteLineItems(Id opportunityId) {
return [SELECT Id, QuoteId, Product2Id, Quantity, UnitPrice, TotalPrice
FROM QuoteLineItem
WHERE Quote.OpportunityId = :opportunityId];
}
@AuraEnabled
public static void saveQuoteLineItems(List<QuoteLineItem> quoteLineItems) {
upsert quoteLineItems;
}
@AuraEnabled
public static void deleteQuoteLineItem(Id quoteLineItemId) {
delete [SELECT Id FROM QuoteLineItem WHERE Id = :quoteLineItemId];
}
}
1.2 LWCコンポーネント
HTML: quoteLineItemTable.html
<template>
<lightning-card title="見積明細(QuoteLineItem)">
<div class="slds-m-around_medium">
<lightning-datatable
key-field="Id"
data={quoteLineItems}
columns={columns}
draft-values={draftValues}
onsave={handleSave}
onrowaction={handleRowAction}>
</lightning-datatable>
<lightning-button
label="行を追加"
onclick={addRow}
class="slds-m-top_medium">
</lightning-button>
<p class="slds-m-top_medium">
<strong>合計金額: {totalAmount} 円</strong>
</p>
</div>
</lightning-card>
</template>
JavaScript: quoteLineItemTable.js
import { LightningElement, api, track, wire } from 'lwc';
import getQuoteLineItems from '@salesforce/apex/QuoteLineItemController.getQuoteLineItems';
import saveQuoteLineItems from '@salesforce/apex/QuoteLineItemController.saveQuoteLineItems';
import deleteQuoteLineItem from '@salesforce/apex/QuoteLineItemController.deleteQuoteLineItem';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
const COLUMNS = [
{ label: '商品ID', fieldName: 'Product2Id', editable: true },
{ label: '数量', fieldName: 'Quantity', type: 'number', editable: true },
{ label: '単価', fieldName: 'UnitPrice', type: 'currency', editable: true },
{ label: '合計', fieldName: 'TotalPrice', type: 'currency' },
{ type: 'action', typeAttributes: { rowActions: [{ label: '削除', name: 'delete' }] } }
];
export default class QuoteLineItemTable extends LightningElement {
@api recordId;
@track quoteLineItems = [];
columns = COLUMNS;
draftValues = [];
@wire(getQuoteLineItems, { opportunityId: '$recordId' })
wiredQuoteLineItems({ error, data }) {
if (data) {
this.quoteLineItems = data;
} else if (error) {
this.showToast('エラー', '見積明細の取得に失敗しました', 'error');
}
}
get totalAmount() {
return this.quoteLineItems.reduce((sum, item) => sum + (item.TotalPrice || 0), 0);
}
handleSave(event) {
const updatedFields = event.detail.draftValues;
saveQuoteLineItems({ quoteLineItems: updatedFields })
.then(() => {
this.showToast('成功', '見積明細が更新されました', 'success');
return refreshApex(this.wiredQuoteLineItems);
})
.catch(error => {
this.showToast('エラー', '保存に失敗しました', 'error');
});
}
handleRowAction(event) {
const actionName = event.detail.action.name;
const row = event.detail.row;
if (actionName === 'delete') {
deleteQuoteLineItem({ quoteLineItemId: row.Id })
.then(() => {
this.showToast('成功', '行を削除しました', 'success');
return refreshApex(this.wiredQuoteLineItems);
})
.catch(error => {
this.showToast('エラー', '削除に失敗しました', 'error');
});
}
}
addRow() {
const newItem = {
Id: 'new_' + Date.now(),
Product2Id: '',
Quantity: 1,
UnitPrice: 0,
TotalPrice: 0
};
this.quoteLineItems = [...this.quoteLineItems, newItem];
}
showToast(title, message, variant) {
this.dispatchEvent(new ShowToastEvent({ title, message, variant }));
}
}
メタデータXML: quoteLineItemTable.js-meta.xml
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata"
fqn="quoteLineItemTable">
<apiVersion>58.0</apiVersion>
<isExposed>true</isExposed>
<targets>
<target>lightning__RecordPage</target>
</targets>
<targetConfigs>
<targetConfig targets="lightning__RecordPage">
<property name="recordId" type="String" label="レコードID" />
</targetConfig>
</targetConfigs>
</LightningComponentBundle>
2. 実装ポイント
-
データの取得
-
@wire(getQuoteLineItems, { opportunityId: '$recordId' })
を使用し、Apexからデータ取得。
-
-
リアルタイムで合計金額を計算
-
get totalAmount()
を利用し、quoteLineItems
の合計金額を計算。
-
-
見積明細の編集・保存
-
lightning-datatable
のonsave
イベントをhandleSave
で処理。
-
-
行の追加・削除
-
addRow()
で仮の新規レコードを追加。 -
handleRowAction()
でdeleteQuoteLineItem
を呼び出し削除。
-
3. まとめ
このLWCは、Salesforceの標準画面では実現できない「動的なUI」 を提供し、
✅ リアルタイムでデータ変更
✅ ダイナミックなUI操作
✅ Apexと連携したデータ管理
を可能にします。
このパターンを応用すれば、リアルタイム在庫チェックやガントチャート表示 なども実装できます!🎯
全体のまとめ
LWCが必要なケースは、
✅ リアルタイム更新(在庫チェック・WebSocket・Platform Events)
✅ 複雑なUI操作(ドラッグ&ドロップ・カスタム検索)
✅ 即時フィードバック(インタラクティブなフォーム・データプレビュー)
が求められる場面です。
Apex + LWCを組み合わせることで、Salesforce標準UIでは難しい高度な画面開発を実現できます!