Lightning コンポーネント開発 TIPS: フローをモーダル表示する方法


最近なにかと注目を集めているフローですが、今回はそのフローについてです。
事前に Flow Designer で作成したフローをカスタム Lightning コンポーネントでモーダル表示する方法をご紹介します。

動作イメージ

  • リードのレコード詳細ページに配置されたフローを開始 ボタンを押すと、事前に作成した ExampleFlow というフローがモーダル表示されています。
  • フロー自体は2つのスクリーンで構成されており、ぞれぞれ以下の様に作成しています。
    • 1枚目: 入力変数に渡されたリードのレコードIDを表示
    • 2枚目: 「最後のページです。」というメッセージを表示
  • フローが終了するとモーダルも自動で閉じます。

コンポーネントの実装例

  • フローをモーダルで表示するFlowButton という Lightning コンポーネントを作成します。
  • ボタンが押されると、 lightning:overlayLibrary を利用してモーダルを表示した後、 lightning:flow によりフローが開始されます。
  • フローに引数を渡したい時は、lightning:flow を開始する時に値を渡します。(フロー側に入力変数を作成するのを忘れないように!)
FlowButton.cmp
<aura:component implements="flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId" access="global" >
    <!-- Global Attributes -->
    <aura:attribute access="global" type="String" name="label"    default="フローの開始" />
    <aura:attribute access="global" type="String" name="flowName" default="ExmapleFlow" />

    <!-- Private Attributes -->
    <aura:attribute access="private" type="Aura.component" name="modal" />

    <!-- Overlay Library -->
    <lightning:overlayLibrary aura:id="overlayLib"/>

    <!-- User Interface -->
    <div>
        <lightning:button variant="brand" label="{!v.label}" onclick="{!c.onButtonClicked}"/>
    </div>    
</aura:component>
FlowButtonController.js
({
    onButtonClicked : function(c, e, h) {
        h.createComponent(c, h, "lightning:flow", {
            onstatuschange: c.get("c.onStatusChanged"),
        })
        .then($A.getCallback(function (flow) {
            c.find("overlayLib").showCustomModal({
                body: flow
            })
            .then($A.getCallback(function(modal) {
                c.set("v.modal", modal);
                flow.startFlow(c.get("v.flowName"), [{ 
                    name : "recordId", 
                    type : "String",
                    value: c.get("v.recordId") 
                }]);
            }));
        }))
        .catch(function(reason) {
            console.error(reason);
        }); 
    },
    onStatusChanged: function (c, e, h) {
        switch(e.getParam("status")) {
            case "FINISHED":
                c.get("v.modal").close();
                break;
            case "FINISHED_SCREEN":
            case "STARTED":
            case "PAUSED":
            case "ERROR":
                break;
        }
    },
})
FlowButtonHelper.js
({
    createComponent: function(c, h, componentDef, componentAttributes) {
        return new Promise(function (resolve, reject) {
            $A.createComponent(componentDef, componentAttributes, function(newComponent, status, errorMessage){
                if (status === "SUCCESS") resolve(newComponent);
                else if (status === "ERROR") reject(errorMessage);
            });
        });
    }
})