Salesforce: lightning:picklistPathを使った2段階のステータス表示の実装
前に上記のような2段階でのステータス表示について、lightning:picklistPathを使ったアイデアを書きました。
crmprogrammer38.hatenablog.com
そのアイデアの実装内容になります。
実装内容
- パスによる1段階目のステータスと、lightning:picklistPathによる2段階目のステータスを表示
- 2段階目のステータスは1段階目のステータスの連動項目のみを表示
- 2段階目のステータスのリスト値をクリックすると確認ダイアログを表示後、値を変更する。
オブジェクト項目
オブジェクト:サブのパス(SubPath__c)
選択リスト(制御):ステータスLv1(StatusLv1__c)
選択リスト(連動):ステータスLv2(StatusLv2__c)
選択リストの連動関係
ステータスLv1 | ステータス1 | ステータス2 | ステータス3 | ステータス4 | ステータス5 |
ステータスLv2 | ステータスA | ||||
ステータスB | |||||
ステータスC | ステータスC | ||||
ステータスD | ステータスD | ||||
ステータスE | ステータスE | ステータスE | |||
ステータスF | ステータスF | ステータスF | |||
ステータスG | ステータスG | ステータスG | |||
ステータスH | ステータスH | ||||
ステータスI | ステータスI | ステータスI | |||
ステータスJ | ステータスJ | ||||
ステータスK | ステータスK |
ステータスLv2の連動設定に対応する選択リスト項目
ステータスLv2_1(StatusLv2_1__c):ステータス1の連動項目
ステータスLv2_2(StatusLv2_2__c):ステータス2の連動項目
ステータスLv2_3(StatusLv2_3__c):ステータス3の連動項目
ステータスLv2_4(StatusLv2_4__c):ステータス4の連動項目
ステータスLv2_5(StatusLv2_5__c):ステータス5の連動項目
作成したトリガ
今回の実装では、ステータスLv2の連動設定に対応する選択リスト項目を用意したので、その項目は常にステータスLv2と同期するようにトリガを作成した。
trigger SubPathTrigger on SubPath__c (before insert , before update) { for(SubPath__c newrow : Trigger.New ){ //常に同期する newrow.StatusLv2_1__c = newrow.StatusLv2__c; newrow.StatusLv2_2__c = newrow.StatusLv2__c; newrow.StatusLv2_3__c = newrow.StatusLv2__c; newrow.StatusLv2_4__c = newrow.StatusLv2__c; newrow.StatusLv2_5__c = newrow.StatusLv2__c; } }
作成したクラス
lightning:picklistPathの表示で、どの選択リスト項目を表示するかの制御と lightning:picklistPath上で選択したリスト値を更新する処理を作成した。
public without sharing class SubPathPickList { //ステータスLv1の値に応じて表示する選択リストのフィールドを返す @AuraEnabled public static String getLv2PickFieldName(String salesforceId){ Listrows = [select Id, StatusLv1__c From SubPath__c where Id =:salesforceId ]; Map<String, String> fieldMapForLv1 = new Map<String,String>(); fieldMapForLv1.put('ステータス1','StatusLv2_1__c'); fieldMapForLv1.put('ステータス2','StatusLv2_2__c'); fieldMapForLv1.put('ステータス3','StatusLv2_3__c'); fieldMapForLv1.put('ステータス4','StatusLv2_4__c'); fieldMapForLv1.put('ステータス5','StatusLv2_5__c'); String fieldName = 'StatusLv2_1__c'; if( rows.isEmpty() == false){ if( fieldMapForLv1.get(rows[0].StatusLv1__c) != null ){ fieldName = fieldMapForLv1.get(rows[0].StatusLv1__c); } } return fieldName; } //ステータスLv2の値を更新 @AuraEnabled public static Boolean setLv2PickFieldValue(String salesforceId, String pickValue){ List rows = [select Id From SubPath__c where Id =:salesforceId ]; if( rows.isEmpty() == true){ return false; } rows[0].StatusLv2__c =pickValue ; try{ update rows; return true; } catch( Exception ex){ return false; } } }
作成したLightning Component
モーダル確認ダイアログ用にbodyとfooterを用意
[ConfirmDialogBody] Component
<aura:component>
<aura:attribute name="messageText" type="String"></aura:attribute>
<div class="slds-align_absolute-center">{!v.messageText}</div>
</aura:component>
[ConfirmDialogFooter] Component
<aura:component>
<aura:attribute name="modalResult" type="String"></aura:attribute>
<lightning:overlaylibrary aura:id="overlayLib"></lightning:overlaylibrary>
<lightning:button variant="neutral" label="キャンセル" onclick="{! c.handleCancel }"></lightning:button>
<lightning:button variant="brand" label="OK" onclick="{! c.handleOK }"></lightning:button>
</aura:component>
[ConfirmDialogFooter] Component
({
handleOK: function(cmp, event, helper) {
cmp.set("v.modalResult", "OK");
cmp.find("overlayLib").notifyClose();
},
handleCancel: function(cmp, event, helper) {
cmp.set("v.modalResult", "Cancel");
cmp.find("overlayLib").notifyClose();
}
});
Lightningページ上に表示するLightning Component
[SubPath] Component
<aura:component
controller="SubPathPickList"
implements="flexipage:availableForAllPageTypes,force:hasRecordId"
access="global"
>
<lightning:overlayLibrary aura:id="overlayLib" />
<aura:attribute name="recordId" type="String" />
<aura:attribute name="modalResult" type="String" />
<aura:attribute name="pickField" type="String" default="StatusLv2_1__c" />
<aura:handler name="init" value="{!this}" action="{!c.doInit}" />
<aura:handler event="force:refreshView" action="{!c.doInit}" />
<lightning:picklistPath
aura:id="picklistPath"
recordId="{!v.recordId}"
variant="non-linear"
picklistFieldApiName="{!v.pickField}"
onselect="{!c.handleSelect}"
></lightning:picklistPath>
</aura:component>
[SubPath] Controller
({
doInit: function(component, event, helper) {
var recordId = component.get("v.recordId");
var fetchEventAction = component.get("c.getLv2PickFieldName");
fetchEventAction.setParams({ salesforceId: recordId });
fetchEventAction.setCallback(this, function(response) {
var fieldName = response.getReturnValue();
component.set("v.pickField", fieldName);
});
$A.enqueueAction(fetchEventAction);
},
handleSelect: function(component, event, helper) {
var recordId = component.get("v.recordId");
var stepName = event.getParam("detail").value;
$A.createComponents(
[
[
"c:ConfirmDialogBody",
{ messageText: "ステータスLv2を" + stepName + "に更新しますか?" }
],
[
"c:ConfirmDialogFooter",
{ modalResult: component.getReference("v.modalResult") }
]
],
function(components, status) {
if (status == "SUCCESS") {
component.find("overlayLib").showCustomModal({
header: "ステータスLv2を更新",
body: components[0],
footer: components[1],
showCloseButton: true,
closeCallback: function() {
if (component.get("v.modalResult") == "OK") {
var updateAction = component.get("c.setLv2PickFieldValue");
updateAction.setParams({
salesforceId: recordId,
pickValue: stepName
});
updateAction.setCallback(this, function(response) {
if (
response.getState() == "SUCCESS" &&
response.getReturnValue()
) {
$A.get("e.force:refreshView").fire();
//refreshViewと同じタイミングでtoastの再描画を防ぐ
window.setTimeout(
$A.getCallback(function() {
var toastEvent = $A.get("e.force:showToast");
toastEvent.setParams({
message: stepName + "に更新しました。",
type: "success"
});
toastEvent.fire();
}),
1000
);
} else {
var toastEvent = $A.get("e.force:showToast");
toastEvent.setParams({
message: stepName + "の更新に失敗しました。",
type: "error"
});
toastEvent.fire();
}
});
$A.enqueueAction(updateAction);
}
}
});
}
}
);
}
});
最後に
lightning:picklistPathの「onselect」アクションでは、選択された選択リスト値のAPI参照名が取得できます。表示ラベルは取得できないので表示ラベルを使いたい場合は、Apexで取得してくるなどの処理が必要になります。