LoginSignup
20
11

More than 3 years have passed since last update.

Aura コンポーネント開発 TIPS: モーダル画面の作り方

Last updated at Posted at 2018-08-31

この記事では、Aura プログラミングモデルにおけるカスタムモーダル画面の作成方法をご紹介します。

モーダルの作成方法の種類

Aura でモーダル画面を作成するにはいくつかの方法がありますが、今回はよく使うであろう2通りをご紹介します。
それぞれに利点がありますが、実装方法が大きく異なるのでご注意ください。

  • lightning:overlayLibrary を使った方法
    • 動的にモーダル画面を作成し、都度コンポーネントインスタンスの作成と削除を行う
    • ヘッダー、ボディ、フッターをコンポーネント化するので、同様のモーダルを大量に作成する場合は再利用性が高まる
  • Salesforce Lightning Design System を使った方法
    • 静的なモーダル画面を作成し、SLDS のクラスの付け替えで表示を制御する
    • 一つのコンポーネントで完結するので、ちょっとしたモーダルを作りたいときに便利

lightning:overlayLibrary を使った方法

overlay.gif

ボディとフッターが連携する

通常のモーダルの使い方として、ボディにフォームを配置しフッターに保存ボタンを配置することがあります。
しかし、lightning:overlayLibrary ではボディとフッターが別コンポーネントとなるため、互いに連携する手段が必要です。

例: フッターで「保存」が押されたら、ボディで保存処理をする

今回は アプリケーションイベント を使った連携方法も合わせてご紹介します。

イベントを作成

CustomModalEvent.evt
<aura:event type="APPLICATION" description="Custom Modal Event">
  <aura:attribute type="String" name="type" /> <!-- SAVE/ERROR -->
</aura:event>

フッターを作成

CustomModalFooter.cmp
<aura:component>
  <!-- Private Attributes -->
  <aura:attribute access="private" type="Boolean" name="isDisabled" default="false" />

  <!-- Registered Events -->
  <aura:registerEvent type="c:CustomModalEvent" name="customModalEvent" />

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

  <!-- User Interface -->
  <div>
    <lightning:button label="キャンセル" onclick="{!c.onCancelClicked}" disabled="{!v.isDisabled}" />
    <lightning:button label="保存" variant="brand" onclick="{!c.onSaveClicked}" disabled="{!v.isDisabled}" />
  </div>
</aura:component>
CustomModalFooterController.js
({
  onCancelClicked: function(c, e, h) {
    c.find('overlayLib').notifyClose();
  },
  onSaveClicked: function(c, e, h) {
    c.set('v.isDisabled', true);
    $A.get(`e.c:CustomModalEvent`)
      .setParams({
        type: 'SAVE'
      }).fire();
  }
});

ボディを作成

CustomModalBody.cmp
<aura:component>
  <!-- Public Attributes -->
  <aura:attribute access="public" type="String" name="lastName" />
  <aura:attribute access="public" type="String" name="firstName" />
  <aura:attribute access="public" type="String" name="email" />

  <!-- Event Handlers -->
  <aura:handler event="c:CustomModalEvent" action="{!c.onCustomModalEvent}" />

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

  <!-- User Interface -->
  <div>
    <lightning:input type="text" label="姓" value="{!v.lastName}" />
    <lightning:input type="text" label="名" value="{!v.firstName}" />
    <lightning:input type="email" label="メール" value="{!v.email}" />

    <lightning:spinner aura:id="spinner" class="slds-hide" variant="brand" size="large" />
  </div>
</aura:component>

CustomModalBodyController.js
({
  onCustomModalEvent: function(c, e, h) {
    const eventType = e.getParams().type;
    if (eventType === 'SAVE') {
      h.showSpinner(c);

      // TODO: ここで値の保存処理をする

      // 保存が完了したらモーダルを閉じる
      setTimeout($A.getCallback(function() {
        h.hideSpinner(c);
        c.find('overlayLib').notifyClose();
      }), 3000);
    }
  }
});
CustomModalBodyHelper.js
({
  showSpinner: function(c) {
    const spinner = c.find('spinner');
    $A.util.removeClass(spinner, 'slds-hide');
  },
  hideSpinner: function(c) {
    const spinner = c.find('spinner');
    $A.util.addClass(spinner, 'slds-hide');
  }
});
CustomModalBody.css
.THIS {
  position: relative;
}

モーダルを呼び出すには...

CustomModalButton.cmp
<aura:component access="global" implements="flexipage:availableForAllPageTypes,forceCommunity:availableForAllPageTypes">
  <!-- Overlay Library -->
  <lightning:overlayLibrary aura:id="overlayLib" />

  <!-- User Interface -->
  <lightning:button variant="brand" label="モーダルを開く" onclick="{!c.onButtonClick}" />
</aura:component>
CustomModalButtonController.js
({
  onButtonClick: function(c, e, h) {
    // モーダルボディのコンポーネントを作成
    const createCustomModalBodyPromise = h.createComponent(c, h, 'c:CustomModalBody', {
      lastName: '',
      firstName: '恵美',
      email: 'ehayashi@example.com'
    });

    // モーダルフッターのコンポーネントを作成
    const createCustomModalFooterPromise = h.createComponent(c, h, 'c:CustomModalFooter', {});

    Promise.all([createCustomModalBodyPromise, createCustomModalFooterPromise])
      .then(
        $A.getCallback(function([customModalBody, customModaFooter]) {
          c.find('overlayLib').showCustomModal({
            header: '顧客情報の編集',
            body: customModalBody,
            footer: customModaFooter
          });
        })
      )
      .catch(function(reason) {
        console.error(reason);
      });
  }
});
CustomModalButtonHelper.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);
      });
    });
  }
});

Salesforce Lightning Design System を使った方法

static.gif

モーダル本体を作成

CustomModal.cmp
<aura:component access="global">

    <!-- Public Attributes -->
    <aura:attribute access="public" type="String" name="header"  />
    <aura:attribute access="public" type="String" name="lastName"  />
    <aura:attribute access="public" type="String" name="firstName"  />
    <aura:attribute access="public" type="String" name="email"  />

    <!-- Privte Attributes -->
    <aura:attribute access="private" type="Boolean" name="showModal" default="false" />

    <!-- Component Method -->
    <aura:method name="open" action="{!c.onOpenCalled}" />

    <!-- User Interface -->
    <div>
        <section role="dialog" tabindex="-1" class="{!'slds-modal' + if(v.showModal, ' slds-fade-in-open', '')}">
            <div class="slds-modal__container">
                <header class="slds-modal__header">
                    <lightning:buttonIcon size="large" class="slds-modal__close" iconName="utility:close" variant="bare-inverse" title="close" alternativeText="Close window" onclick="{!c.onCloseClicked}"/>
                    <h2 class="slds-text-heading_medium slds-hyphenate">{!v.header}</h2>
                </header>
                <div class="slds-modal__content slds-p-around_medium">
                    <lightning:input type="text"  label="姓"     value="{!v.lastName}"/>
                    <lightning:input type="text"  label="名"     value="{!v.firstName}"/>
                    <lightning:input type="email" label="メール" value="{!v.email}"/>
                </div>
                <footer class="slds-modal__footer">
                    <lightning:button label="キャンセル" onclick="{!c.onCancelClicked}" />
                    <lightning:button label="保存" variant="brand" onclick="{!c.onSaveClicked}" />
                </footer>
            </div>
             <lightning:spinner aura:id="spinner" class="slds-hide" variant="brand" size="large" />
        </section>
        <div class="{!'slds-backdrop' + if(v.showModal, ' slds-backdrop_open', '')}"></div>
    </div>
</aura:component>
CustomModalController.js
({
    onOpenCalled: function(c, e, h) {
        c.set('v.showModal', true);
    },
    onCloseClicked: function(c, e, h) {
        c.set('v.showModal', false);
    },
    onCanceClicked: function(c, e, h) {
        c.set('v.showModal', false);
    },
    onSaveClicked:  function(c, e, h) {
        h.showSpinner(c);

        // TODO: ここで値の保存処理をする

        // 保存が完了したらモーダルを閉じる
        setTimeout($A.getCallback(function() {
            h.hideSpinner(c);
            c.set('v.showModal', false);
        }), 3000);
    },
})
CustomModalHelper.js
({
  showSpinner: function(c) {
    const spinner = c.find('spinner');
    $A.util.removeClass(spinner, 'slds-hide');
  },
  hideSpinner: function(c) {
    const spinner = c.find('spinner');
    $A.util.addClass(spinner, 'slds-hide');
  }
});

モーダルを呼び出すには...

CustomModalButton.cmp
<aura:component access="global" implements="flexipage:availableForAllPageTypes,forceCommunity:availableForAllPageTypes">
  <!-- User Interface -->
  <lightning:button variant="brand" label="モーダルを開く" onclick="{!c.onButtonClick}" />

  <c:CustomModal aura:id="modal" header="顧客情報の編集" lastName="林" firstName="恵美" email="ehayashi@example.com" />
</aura:component>
CustomModalButtonController.js
({
  onButtonClick: function(c, e, h) {
    c.find('modal').open();
  }
});
20
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
11