Salesforce Accountアクションボタン実装ガイド
Salesforce Accountアクションボタン実装ガイド
以下に完全な実装内容を保存用にまとめます。このコードはAccountオブジェクトにアクションボタンを追加し、クリック時に外部サイトを新しいタブで開く機能を提供します。
完全な実装ファイル
- LWCコンポーネント: accountButton.js
javascript
import { LightningElement, api } from ‘lwc’;
import getAccountData from ‘@salesforce/apex/AccountController.getAccountData’;
import { CloseActionScreenEvent } from ‘lightning/actions’;
// 外部サイトのベースURL(実際のURLに置き換えてください)
const EXTERNAL_BASE_URL = ‘https://your-external-site.com/data?accountName=’;
export default class AccountButton extends LightningElement {
@api recordId; // Salesforceから自動で渡されるレコードID
// アクションボタンがクリックされたときに呼び出されるメソッド
@api
async invoke() {try {// まずモーダルをすぐに閉じる(重要)this.closeActionModal();// Apexメソッドを呼び出してAccountデータを取得const accountData = await getAccountData({ accountId: this.recordId });if (!accountData) {throw new Error('Accountデータが取得できませんでした');}// Account名を取得const accountName = accountData.Name;// アカウント名をURLエンコードconst encodedName = encodeURIComponent(accountName);const fullUrl = EXTERNAL_BASE_URL + encodedName;// 外部サイトを新しいタブで開くthis.openExternalSite(fullUrl);} catch (error) {console.error('エラーが発生しました:', error.message);// 実際のアプリケーションではユーザーへのエラー通知を追加}
}// window.openを使用した外部サイトへのナビゲーション
openExternalSite(url) {// setTimeoutで実行コンテキストを変更(ポップアップブロック対策)setTimeout(() => {// セキュリティ強化オプション付きで新しいタブを開くwindow.open(url, '_blank', 'noopener,noreferrer');}, 0);
}// アクションモーダルを閉じるメソッド
closeActionModal() {this.dispatchEvent(new CloseActionScreenEvent());
}
}
2. LWCテンプレート: accountButton.html
html
3. LWC設定ファイル: accountButton.js-meta.xml
xml
Salesforce CLIでデプロイ:
bash
Apexクラスをデプロイ
sfdx force:source:deploy -p force-app/main/default/classes/AccountController.cls
LWCコンポーネントをデプロイ
sfdx force:source:deploy -p force-app/main/default/lwc/accountButton
設定手順
Salesforce設定に移動:
オブジェクトマネージャ → Account
アクションを追加:
「ボタン、リンク、およびアクション」タブを選択
「アクションの更新」をクリック
カスタムアクションを選択:
カスタムアクションからaccountButtonを選択
レイアウトに追加
プロファイル権限を確認:
ユーザープロファイルにApexクラスとLWCコンポーネントへのアクセス権があるか確認
動作説明
ユーザー操作:
Account詳細ページでアクションボタン(右上のドットメニュー)をクリック
内部処理:
Salesforceが自動的にinvoke()メソッドを呼び出し
モーダルが即時閉じられる
ApexコントローラからAccountデータを取得
URLを構築して外部サイトを新しいタブで開く
結果:
外部サイトが新しいブラウザタブで開く
URLにはAccount名がパラメータとして渡される
Salesforce内で不要なポップアップが表示されない
カスタマイズポイント
複数フィールドを使用する場合
javascript
// accountButton.js
// …
@api
async invoke() {
try {
this.closeActionModal();
const accountData = await getAccountData({ accountId: this.recordId });
// URLパラメータを構築const params = new URLSearchParams({name: accountData.Name,industry: accountData.Industry || '',type: accountData.Type || '',id: this.recordId});const fullUrl = EXTERNAL_BASE_URL + params.toString();this.openExternalSite(fullUrl);
} catch (error) {console.error('エラーが発生しました:', error.message);
}
}
// …
apex
// AccountController.cls
public with sharing class AccountController {
@AuraEnabled(cacheable=true)
public static Account getAccountData(String accountId) {
try {
// 複数フィールドを取得
return [
SELECT Id, Name, Industry, Type
FROM Account
WHERE Id = :accountId
LIMIT 1
];
} catch (Exception e) {
throw new AuraHandledException('Accountデータの取得に失敗しました: ’ + e.getMessage());
}
}
}
ポップアップブロック対策強化版
javascript
// accountButton.js
// …
openExternalSite(url) {
// ユーザーアクションのフラグ
const userTriggered = true;
setTimeout(() => {// 新しいタブを開くconst newWindow = window.open('', '_blank');if (newWindow) {// ポップアップブロックされていない場合newWindow.location.href = url;newWindow.opener = null; // セキュリティ対策} else if (userTriggered) {// ポップアップブロックされた場合の代替処理alert('ポップアップがブロックされました。手動でサイトを開いてください: ' + url);}
}, 0);
}
// …
トラブルシューティング
Apexクラスが見つからないエラー:
クラス名が正しいか確認
デプロイが成功しているか確認: sfdx force:source:status
プロファイル権限を確認
ボタンが表示されない:
js-meta.xmlの設定を確認
ページレイアウトにアクションが追加されているか確認
プロファイル権限を確認
外部サイトが開かない:
ブラウザのポップアップブロックを確認
console.errorの内容を確認
setTimeoutの値を増やす(例: setTimeout(() => {…}, 100))
この実装は、Account詳細ページのアクションボタンクリック時に外部サイトを新しいタブで開くシンプルで効果的なソリューションです。モーダルを即時閉じることでSalesforceの標準動作をキャンセルし、window.openを使用することで意図しないポップアップ表示を防いでいます。
–
// accountButton.js
import { LightningElement, api } from 'lwc';
import getAccountData from '@salesforce/apex/AccountController.getAccountData';
import { CloseActionScreenEvent } from 'lightning/actions';
const EXTERNAL_BASE_URL = 'https://your-external-site.com/data?accountName=';
export default class AccountButton extends LightningElement {@api recordId;@apiasync invoke() {try {// まずモーダルをすぐに閉じるthis.closeActionModal();// データ取得処理const accountData = await getAccountData({ accountId: this.recordId });if (!accountData) {throw new Error('Accountデータが取得できませんでした');}const accountName = accountData.Name;const encodedName = encodeURIComponent(accountName);const fullUrl = EXTERNAL_BASE_URL + encodedName;// window.openを使用して外部サイトを新しいタブで開くthis.openExternalSite(fullUrl);} catch (error) {console.error('エラーが発生しました:', error.message);}}// window.openを使用した外部サイトへのナビゲーションopenExternalSite(url) {// setTimeoutで実行コンテキストを変更setTimeout(() => {// セキュリティ強化オプション付きwindow.open(url, '_blank', 'noopener,noreferrer');}, 0);}closeActionModal() {this.dispatchEvent(new CloseActionScreenEvent());}
}
<!-- accountButton.html -->
<template></template>
<!-- accountButton.js-meta.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata"><apiVersion>58.0</apiVersion><isExposed>true</isExposed><targets><target>lightning__RecordAction</target></targets><targetConfigs><targetConfig targets="lightning__RecordAction"><actionType>Action</actionType><objects><object>Account</object></objects></targetConfig></targetConfigs>
</LightningComponentBundle>
// AccountController.cls
public with sharing class AccountController {@AuraEnabled(cacheable=true)public static Account getAccountData(String accountId) {try {return [SELECT Id, Name FROM Account WHERE Id = :accountId LIMIT 1];} catch (Exception e) {throw new AuraHandledException('Accountデータの取得に失敗しました: ' + e.getMessage());}}
}
ファイル構造
force-app/
└── main/└── default/├── classes/│ └── AccountController.cls└── lwc/└── accountButton/├── accountButton.html├── accountButton.js└── accountButton.js-meta.xml
デプロイコマンド
# すべてのファイルをデプロイ
sfdx force:source:deploy -p force-app/main/default
追加の最適化オプション
// window.open の拡張版(ポップアップブロック対策)
openExternalSite(url) {const userTriggered = true; // ユーザーアクションによる実行フラグsetTimeout(() => {const newWindow = window.open('', '_blank');if (newWindow) {newWindow.opener = null;newWindow.location.href = url;} else if (userTriggered) {alert('ポップアップがブロックされました。手動でサイトを開いてください: ' + url);}}, 0);
}
保存のための便利なツール
- Visual Studio Code: 各ファイルを個別に作成し、フォルダ構造で保存
- Salesforce CLI: プロジェクトとして保存
# 新しいプロジェクト作成 sfdx force:project:create -n AccountActionButton # ファイルを適切なパスに配置
この内容をテキストファイルやコードエディタに保存してください。特に4つのファイル(JS, HTML, XML, Apex)は、指定されたパス構造で保存することが重要です。