プログラマ38の日記

主にプログラムメモです。

Salesforce: lightning:picklistPathを使った2段階のステータス表示の実装

f:id:crmprogrammer38:20200426163432p:plain

前に上記のような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){    
        
        List rows = [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で取得してくるなどの処理が必要になります。