ステップバイステップでLightningコンポーネントを楽しもう！ - モジュール10


# コンポーネントを組み合わせてイベントを処理してみよう

## 画面イメージ

<img src="https://qiita-image-store.s3.amazonaws.com/0/86505/6008a2c1-7cea-d111-20d0-7528f0348c52.png" width="50%"/>

## ソース

### Apex
モジュール9のApexクラス(LeadController.cls)を利用します。

### コンポーネントイベント
モジュール9のコンポーネントイベント(SearchKeyChangeEvent.evt)を利用します。

### アプリケーションイベント

```xml:RecordCreatedEvent
<!-- アプリケーションイベント -->
<aura:event type="APPLICATION">
    <aura:attribute name="id" type="String"/>
</aura:event>
```

### 登録コンポーネント

※force:appHostableは不要なので外します。

```xml:m10_CreateComponent.cmp
<aura:component controller="LeadController">

    <!-- アプリケーションイベント登録 -->
    <aura:registerEvent name="createEvent" type="c:RecordCreatedEvent"/>

    <h3>リード登録</h3>

    <aura:attribute name="lead" type="Lead" default="{ 'sobjectType': 'Lead', 'LastName': '', 'Company': '' }"/>

    <form>
        <ui:inputText aura:id="company" label="会社名" value="{!v.lead.Company}" required="true"/>
        <ui:inputText aura:id="lastname" label="姓" value="{!v.lead.LastName}" required="true"/>
        <ui:button label="登録" press="{!c.createLead}"/>
    </form>

</aura:component>
```

```javascript:m10_CreateComponentController.js
({
    createLead: function(component, event, helper) {

        var isValid = true;
        var company = component.find("company");
        var lastName = component.find("lastname");

        company.setValid("v.value", true);
        lastName.setValid("v.value", true);

        if ($A.util.isEmpty(company.get("v.value"))) {
            company.setValid("v.value", false);
            company.addErrors("v.value", [{message:"会社名を入力してください。"}]);
            isValid = false;
        }
        if ($A.util.isEmpty(lastName.get("v.value"))) {
            lastName.setValid("v.value", false);
            lastName.addErrors("v.value", [{message:"姓を入力してください。"}]);
            isValid = false;
        }

        if (isValid) {
            var lead = component.get("v.lead");
            var action = component.get("c.create");
            action.setParams({
                "ld": lead
            });

            action.setCallback(this, function(a){
                var toastEvent = $A.get("e.force:showToast");
                if (action.getState() === 'SUCCESS') {
                    toastEvent.setParams({
                        "title": "Success",
                        "message": "正常に登録が完了しました"
                    });
                    company.set("v.value", "");
                    lastName.set("v.value", "");

                    // アプリケーションイベント発火
                    var appEvent = $A.get("e.c:RecordCreatedEvent");
                    appEvent.setParams({
                        // 今回は使用しませんがセットしています
                        "id": a.Id
                    });
                    appEvent.fire();

                } else {
                    toastEvent.setParams({
                        "title": "Error",
                        "message": "エラーが発生しました"
                    });
                }
                toastEvent.fire();
            });

            $A.enqueueAction(action);
        }
    },
})
```

### リスト表示コンポーネント

※force:appHostableは不要なので外します。

```xml:m10_ListComponent.cmp
<aura:component controller="LeadController">

    <aura:attribute name="leads" type="Lead[]"/>

    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>

    <!-- コンポーネントイベント登録 -->
    <aura:registerEvent name="searchKeyChange" type="c:SearchKeyChangeEvent"/>
    <!-- コンポーネントイベント購読 -->
    <aura:handler name="searchKeyChange" action="{!c.search}"/>

    <!-- アプリケーションイベント購読 -->
    <aura:handler event="c:RecordCreatedEvent" action="{!c.search}"/>

    <h3>リード表示</h3>
    <ui:inputText aura:id="searchkey" label="検索キー" labelClass="assistiveText" placeholder="姓で検索" keyup="{!c.searchKeyChange}" updateOn="keyup"/>
    <ui:button label="更新" press="{!c.refresh}"/>
    <ul>
        <aura:iteration items="{!v.leads}" var="lead">
            <li>
                <p>
                    {!lead.Company}<br/>
                    {!lead.LastName}
                </p>
            </li>
        </aura:iteration>
    </ul>
</aura:component>
```

※searchメソッドで、eventの属性値を取得している箇所を入力コンポーネントから取得するように変更します。

```javascript:m10_ListComponentController.js
({
    doInit: function(component, event, helper) {
        helper.getLeads(component);
    },
    refresh: function(component, event, helper) {
        var searchKey = component.find("searchkey").get("v.value");
        if ($A.util.isEmpty(searchKey)) {
            searchKey = "";
        }
        helper.getLeadsByName(component, searchKey);
    },
    searchKeyChange: function(component, event, helper) {
        // コンポーネントイベント発火
        var searchKeyChangeEvent = component.getEvent("searchKeyChange");
        searchKeyChangeEvent.setParams({
            "searchKey": component.find("searchkey").get("v.value"),
        });
        searchKeyChangeEvent.fire();
    },
    search: function(component, event, helper) {
        // コンポーネント・アプリケーションイベント処理
        var searchKey = component.find("searchkey").get("v.value");
        if ($A.util.isEmpty(searchKey)) {
            searchKey = "";
        }
        helper.getLeadsByName(component, searchKey);
    },
})
```

```javascript:m10_ListComponentHelper.js
({
    getLeads: function(component) {
        var action = component.get("c.findAll");
        action.setCallback(this, function(a){
            component.set("v.leads", a.getReturnValue());
        });
        $A.enqueueAction(action);
    },
    getLeadsByName: function(component, searchKey) {
        var action = component.get("c.findByLastName");
        action.setParams({
            "searchKey": searchKey
        });
        action.setCallback(this, function(a){
            component.set("v.leads", a.getReturnValue());
        });
        $A.enqueueAction(action);
    }
})
```

### Mixしたコンポーネント

前述の2つのコンポーネントを利用します。

```xml:m10_MixedComponent.cmp
<aura:component implements="force:appHostable">
    <!-- 登録コンポーネント -->
    <c:m10_CreateComponent/>
    <!-- リスト表示コンポーネント -->
    <c:m10_ListComponent/>
</aura:component>
```

## ポイント

### アプリケーションイベント
```<aura:event type="APPLICATION">```と、type属性に「APPLICATION」を指定します。

### アプリケーションイベント登録
```<aura:event type="COMPONENT">```と、type属性に「COMPONENT」を指定します。
※コンポーネントイベントと同じです。


### イベント購読
```<aura:handler event="<名前空間:イベント>" action="{!c.<イベントアクションメソッド名>}"/>```でアプリケーションイベントを購読できます。

### アプリケーションイベント発火
* $Aから```$A.get("e.<名前空間>:<イベント>")```でイベント取得します。
* ```setParams```でパラメータ設定します。
* ```fire```で発火します。

## 補足
* P113 インスタンス化されたコンポーネントのコンポーネントイベントを処理する
* P123 高度なイベントの例

---

# 最後に

これでハンズオンは終了です。
これまでの補足を読んで動作を確認したり、作ったコンポーネントを拡張したり、もくもく遊んでみましょう。

Let's have fun!

---

:arrow_backward: [モジュール9へ](http://qiita.com/UmekitaForce/private/a293fccd027ef6f08321 "モジュール9")