はじめに
Salesforceにて複数のレコードを対象としてアクションを行いたい場合、多くの場合リストビューからレコードにチェックを入れて、その選択情報を引き継いでカスタムアクションを起動したくなります。
リストビューボタンから選択レコードを保持して画面遷移を行う場合には、Visualforceか画面フローを経由する必要があります。
画面フローで済む場合にはそれで全く構わないと思っています。こちらの記事が大変参考になるので是非ご参照ください。
問題は画面フロー以上に作りこんだ機能を実現したい場合です。今の時代、Salesforce上に作りこんだ画面を開発する場合はLWC (Lightning Web Components) を使って開発したいですが、リストビューボタンから選択レコードの情報を保持して直接LWCに遷移する方法は現状ありません (2025年3月現在、IdeaExchangeではOn Roadmapとして上がっている)。
そこで、Visualforceを最小限だけ書いてLWCに橋渡しするためのVisualforceコンポーネントを作ります。
できあがり
Visualforceコンポーネント
このコンポーネントをリストビューから呼び出すVFページで再利用します。
ListButtonRedirect.component
<apex:component>
<apex:attribute
name="records"
type="SObject[]"
description="Records selected in list view."
required="true"
/>
<apex:attribute
name="path"
type="String"
description="Redirect path to new page."
/>
<apex:attribute
name="paramKey"
type="String"
description="Query parameter key of selected record Ids."
default="c__recordIds"
/>
<apex:attribute
name="delimiter"
type="String"
description="Delimiter of selected record Ids."
default=","
/>
<apex:outputPanel rendered="{!NOT(ISBLANK(path))}" layout="none">
<script type="module">
const paramKey = '{!paramKey}';
const recordIds = [
<apex:repeat value="{!records}" var="r">
'{!r.Id}',
</apex:repeat>
];
const url = new URL('{!path}', 'base://base');
if (paramKey.length && recordIds.length) {
url.searchParams.set(paramKey, recordIds.join('{!delimiter}'));
}
sforce.one?.navigateToURL(url.pathname + url.search, true);
</script>
</apex:outputPanel>
</apex:component>
Visualforceページ
各リストビューアクションでこんな感じにコンポーネントを使います(これだけです)。
変更するのはstandardController
のオブジェクト名、path
のリダイレクト先のみです。
LWCを遷移先にする場合は、URL AddressableにするかLightningコンポーネントタブに設定してpathを変更してください。
ListViewPage.page
<apex:page standardController="Account" recordSetVar="records">
<c:ListButtonRedirect
records="{!selected}"
path="/lightning/cmp/c__someLwc"
/>
</apex:page>
リストビューボタンを作成・配置
上記のVisualforceページを作成したら、リストボタンの遷移先として設定しリストビューボタンレイアウトに配置します。
動作確認
リストボタンから選択したレコードのIDをクエリパラメータに保持してLWCに遷移します。ここまでくればLWC側で煮るなり焼くなり好きにすればOKです。
ちょっとした解説
リストビューボタンに設定するVFページでは、StandardSetController
を使用します。標準コントローラーを使っているページでは、getterメソッドが用意されているプロパティについては、基本的にプロパティ名を直接書くことでVFページ内から直接アクセスできます。そこで、選択レコードの情報を{!selected}
としてコンポーネントに渡しています。
コンポーネント側では、その選択レコードの配列をapex:repeat
でJavaScriptに展開して、sforce.one
の機能からリダイレクトしています。
ちなみに、コンポーネントではレコードIDのパラメータキーとデリミタが指定可能になっています。