BLOG

【Salesforce研修】まるの記録9

こんにちは。まるです。
もうすぐハロウィンですね!
今年は三密を避けるべくバーチャル渋谷でのイベントなども企画されているそうで、なかなか楽しそうだなと思っています。

さて、今回は実際に私が作成したVisualforce画面およびコントローラクラスを用いて、開発の流れをざっくりおさらいします。

完成イメージ

今回作成するのは、一つの取引先レコードに関連している取引先責任者の主要項目を一つの画面で編集することが出来る「取引先責任者一括編集画面」です。

本来はそれぞれの取引先責任者の編集ページまで遷移して編集を行わなくてはなりませんが、複数のレコードに対して編集が必要な場合だと手間になるので、一括編集画面で簡単に編集出来るようにしてみます。(データローダ使えば一発じゃんという点はひとまず置いておいてください。今回はユーザが手入力したいという要望があるということで…)

一括編集画面への遷移ボタンは関連リストに配置します。

一括画面の完成形はこんな感じです。
一画面に元の取引先に関連する取引先責任者が全件表示されて、この画面上でレコードの新規作成・削除もできるとベストかなと考えていました。

枠組みを作る

早速画面を作成していきます。
ひとまず、Visualforceを使用して取引先責任者の主要項目を入力できるだけの画面を作成してみました。

<apex:page standardController="Contact" recordSetVar="contacts">
	<apex:form >
		<apex:pageBlock title="取引先責任者一括編集画面">    
			<apex:pageBlockTable title="Contacts" value="{!contacts}" var="con">
				<apex:column headerValue="姓" >
					<apex:inputField value="{!con.LastName}"/>
				</apex:column>
				<apex:column headerValue="名" >
					<apex:inputField value="{!con.FirstName}"/>
				</apex:column>
                <apex:column headerValue="役職" >
					<apex:inputField value="{!con.Title}"/>
				</apex:column>
                <apex:column headerValue="部署" >
					<apex:inputField value="{!con.Department}"/>
				</apex:column>
        	</apex:pageBlockTable>        
		</apex:pageBlock>
	</apex:form>
</apex:page>

なかなかいい感じです。
取引先責任者の情報を取得するので、標準コントローラで”Contact“を指定しています。
ユーザが画面入力を出来るようにしたいので、<apex:form>コンポーネントで入力欄を囲みました。
<apex:pageBlockTable>コンポーネントを利用することで自動でテーブルっぽいレイアウトに整えてくれるのは便利ですね。また、このコンポーネントのvalue属性で<apex:page>のrecordSetVar属性の値(標準コントローラから取得したレコードの集まり)をセットし、var属性で”con”という名称を付けました。
この名称を利用して、入力欄を作成する<apex:inputField>コンポーネントで入力された値をセットする対象の項目を設定しています。

今回はLightning画面から使用したいので、レイアウトもLihtningっぽくしてみます。

<apex:page standardController="Contact" recordSetVar="contacts" LightningStylesheets="true">

なんということでしょう。
Lightningスタイルシートをtrueに設定しただけで、それっぽい画面になりました。

親取引先の情報を取得する

今回は親取引先に関連する取引先責任者のみを絞り込んで表示したいので、カスタムコントローラを使ってやってみましょう。

public class ContactEdit_Controller {
	public Id accountId;	//親取引先のID
    public List < Contact > contactList {get;set;}	//対象の取引先責任者リスト
    
    //コンストラクタ
    public ContactEdit_Controller(ApexPages.StandardSetController controller) {
		accountId = ApexPages.currentPage().getParameters().get('id');
		contactList = [Select id, firstName, LastName, Title, Department from Contact where AccountId = :accountId];
    }
}

コンストラクタの引数で標準セットコントローラを設定します。(取引先責任者レコードをセットで扱うので、標準コントローラではなく標準セットコントローラを使います)

SOQL文で取得する項目はIDと画面上に表示する主要項目、絞り込み条件は“同一の取引先に関連する取引先責任者レコード”です。
同一の取引先に紐づいているかなんてどうやって判断するんだ…?と悩んだのですが、
どうやらApexPages.currentPage().getParameters().get(〇〇)で画面遷移前の情報(パラメータ)を取得することが出来るみたいです。
今回は取引先画面からボタンを押して一括編集画面に遷移する予定なので、get(‘id’)とすれば対象の取引先のレコードIDが取得できます。
これで取引先責任者の親取引先のレコードID(AccountId)が上記で取得したIDと一致する、というWhere文が書けました。

SOQL文で絞り込まれた取引先責任者レコードの集まりは、変数contactListにセットされます。
この変数は3行目でgetter・setterが設定されているので、呼び出し元から変数名だけで簡単に呼び出せます。

コントローラが準備出来たので、先ほどのVisualforce画面に設定してみます。

<apex:page standardController="Contact" recordSetVar="contacts" extensions="ContactsEdit_Controller" LightningStylesheets="true">
    <apex:form >
        <apex:pageBlock title="取引先責任者一括編集画面">    
            <apex:pageBlockTable title="Contacts" value="{!contactList}" var="con">
                <apex:column headerValue="姓" >
                    <apex:inputField value="{!con.LastName}"/>
                </apex:column>
                <apex:column headerValue="名" >
                    <apex:inputField value="{!con.FirstName}"/>
                </apex:column>
                <apex:column headerValue="役職" >
                    <apex:inputField value="{!con.Title}"/>
                </apex:column>
                <apex:column headerValue="部署" >
                    <apex:inputField value="{!con.Department}"/>
                </apex:column>
            </apex:pageBlockTable>        
        </apex:pageBlock>
    </apex:form>
</apex:page>

標準コントローラとカスタムコントローラを同時に使用する際は、extensions属性を使用します。(1行目)
また、<apex:pageBlockTable>のvalue属性を、カスタムコントローラ側の”contactList”に置き換えています。

関連リストボタンの作成

画面の準備は出来ました。この画面を呼び出すリストボタンを作成しましょう。
Salesforceの標準の設定画面から[オブジェクトマネージャ]を選択し、取引先責任者オブジェクトの設定画面へ遷移します。
設定メニューの中から[ボタン、リンク、およびアクション]を選択し、[新規ボタンまたはリンク]ボタンを押下します。

今回は関連リストに表示させたいので、リストボタンを選択します。下図のように先ほど作成したVisualforce画面をコンテンツとして選択し、保存します。

このままだとリンクボタンが作成されただけですので、取引先レイアウトの取引先責任者関連リストにボタンを配置します。

実際に取引先レコードを見てみましょう。

無事一括編集画面に遷移出来ました!ちゃんと遷移元の取引先に関連している取引先責任者のみ表示されてますね。

保存・キャンセル処理の追加

編集画面というからには、この画面で編集した内容が問題なく元のレコードに反映されないといけません。
ということで、[保存]ボタンと[キャンセル]ボタンを画面に追加します。
Visualforceに追加するコードとしては、以下のものだけです。

<apex:pageBlockButtons location="bottom">
	<apex:commandButton value="保存" action="{!save}"/>
	<apex:commandButton value="キャンセル" action="{!cancel}"/>
</apex:pageBlockButtons> 

1行目のlocation属性でボタンの配置箇所を指定しています。今回は下に置きましょう。
標準コントローラでは保存処理やキャンセル処理など一般的なアクションについては既に処理が指定されているため、保存処理を呼び出す際は{!save}、キャンセル処理を呼び出す際は{!cancel}と記述するだけでokです。便利ですね~。
※詳細はこちら

ただ、今回は複数のレコードを一度に更新するので通常の保存アクションでは実行出来ません。
そんなときは、カスタムコントローラで標準アクションの上書きが出来ます。

//保存処理
public PageReference save() {
	upsert contactList;
	String prevURL = '/' + accountId;
	PageReference pageRef = new PageReference(prevURL);
	return pageRef;
}

3行目で画面に表示されている取引先責任者のリストを一括更新しています。
4・5行目では遷移先のURL(取引先レコードの詳細画面のURL)を指定し、6行目でそれを返しています。
よって、このアクションを実行した後は指定されたURLに自動遷移します。

実際に動かしてみます。
今回は「田中 一郎」の役職を担当から主任に変更し、保存ボタンを押してみます。

問題なく元の取引先画面に戻ってきました。

変更内容も反映されています。

これでメインの機能は完成です。
長くなりましたので、続きは次回に回します…。

所感

自分で一からモノを作成するというのはなかなか難しいです。
とはいえ、調べながらでも自分が思うようなモノが完成すると嬉しいですね。これからも精進します。

今回はここまでです。
有難うございました!

BLOGトップへ戻る