【Salesforce】Auraコンポーネント別タブで開く

#Auraコンポーネント別タブで開く
##経緯

　最近プロジェクトにあるAuraコンポーネントを別タブで開くことを望ましい要件が来た。

---

##環境
　Salesクラウドのstandard navigation
　**※**Sales consoleの場合、下記記事を参照して「lightning:workspaceAPI」を利用します。
　[New lightning component opened from another, but tab shoes “Loading…”](https://salesforce.stackexchange.com/questions/233074/new-lightning-component-opened-from-another-but-tab-shoes-loading)

---

##詳細要件

1. あるコンポーネント（次は子コンポーネントと呼びます）を別タブで開く
2. 親コンポーネントから子コンポーネント初期化用パラメータを渡す。

---

##実現概要
- 親コンポーネント

　取引先レコード画面に追加して、該当取引先のIDを取得し、親コンポーネント内の遷移ボタンを押して、子コンポーネントに遷移し、該当取引先のIDをパラメータとして子コンポーネントに渡します。

- 子コンポーネント

　初期処理(initイベント)に親コンポーネントから渡された取引先のIDを取得し、該当IDを使って、必要な情報を取得して、画面に出力します。

---

##概要図
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480807/d21d29e4-7ee7-b79d-197f-a347b004d2fd.png)

---

##実現コード
| No.       |       ファイル名        |
|:----------|:-----------------------|
| 1         |wrapper.cmp             |
| 2         |wrapperController.js    |
| 3         |myAccountController.cls |
| 4         |newtab.cmp              |
| 5         |newtabController.js     |

---

#####1. wrapper.cmp

```html:wrapper.cmp
<aura:component implements="flexipage:availableForRecordHome,force:hasRecordId" access="global">
    <aura:attribute name="record" type="Object" description="The record object to be displayed"/>
    <aura:attribute name="simpleRecord" type="Object" description="A simplified view record object to be displayed"/>
    <aura:attribute name="recordError" type="String" description="An error message bound to force:recordData"/>

    <lightning:navigation aura:id="navigationService" />

    <force:recordData aura:id="record"
        layoutType="FULL"
        recordId="{!v.recordId}"
        targetError="{!v.recordError}"
        targetRecord="{!v.record}"
        targetFields ="{!v.simpleRecord}"
        mode="VIEW"/>
    <lightning:card iconName="standard:account" title="{!v.simpleRecord.Name}" >
        <div class="slds-p-horizontal--small">
            <p class="slds-text-heading--small">
                <lightning:formattedText title="Billing City" value="{!v.simpleRecord.BillingCity}" />&nbsp;&nbsp;　　
                <lightning:formattedText title="Billing State" value="{!v.simpleRecord.BillingState}" /></p>
        </div>
    </lightning:card>
    <lightning:button label="OpenNewTab" title="Neutral action" onclick="{! c.handleClick }"/>
</aura:component>

```

######説明:
　Lightning データサービスのforce:recordDataコンポーネントを使って、取引先レコードの情報を取得して、必要なら、コンポーネント内に表示もできます。表示の必要がなければ、コントローラーにしか使えないも構いません。

---

#####2. wrapperController.js

```javascript:wrapperController.js
({
    handleClick : function(component, event, helper) {

        var navService = component.find("navigationService");
        console.log(component.get("v.simpleRecord.Id"));
        var pageReference = {
            type: 'standard__component',
            attributes: {
                componentName: 'c__newtab',
                pageName: 'Test'
            },
            state: {
                "c__accountId": component.get("v.simpleRecord.Id")
            } 
        };
        const handleUrl = (url) => {
            window.open(url);
        };
        
        const handleError = (error) => {
            console.log(error);
        };

        navService.generateUrl(pageReference).then(handleUrl, handleError);
    }
})
```

######説明
　lightning:navigationを利用して、新タブ開くを実現します。親コンポーネントから子コンポーネントへ遷移の場合、PageReferenceオブジェクトでaccountIdパラメータを渡します。
　    **注意：**PageReferenceのstateでパラメータを渡す場合、Spring ’19から「<font color="Red">**c__**</font>」を命名空間接頭語としてつかいなければならない。

---
######3. myAccountController.cls

```java:myAccountController.cls
public with sharing class myAccountController {
    public myAccountController() {

    }

    @AuraEnabled
    public static Account getAccountById(String accountId) {

        System.debug(accountId);

        Account result = [select id, name, BillingAddress from Account Where Id = :accountId];
        return result;
    }
}
```

######説明
　単純な取引先のIDにより、必要な属性しかを取得しない処理です。

---

######4. newtab.cmp

```html:newtab.cmp
<aura:component implements="lightning:isUrlAddressable,force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,forceCommunity:availableForAllPageTypes" controller="myAccountController" access="global">
    <aura:attribute name="acccountInfo" type="Object" />
    <aura:handler name="init" value="{!this}" action="{!c.init}" />
    <lightning:layout class="slds-page-header slds-page-header--object-home">
        <lightning:layoutItem>
            <lightning:icon iconName="standard:scan_card" alternativeText="My Account"/>
        </lightning:layoutItem>
        <lightning:layoutItem padding="horizontal-small">
            <div class="page-section page-header">
                <h1 class="slds-text-heading--label">Account</h1>
                <h2 class="slds-text-heading--medium">My Account</h2>
            </div>
        </lightning:layoutItem>
    </lightning:layout>
    <lightning:layout>
        <lightning:layoutItem padding="around-small" size="6">
            <div aria-labelledby="newexpenseform">
                <!-- BOXED AREA -->
                <fieldset class="slds-box slds-theme--default slds-container--small">
                <legend id="newexpenseform" class="slds-text-heading--small 
                  slds-p-vertical--medium">
                  Show Account
                </legend>
                    <div class="slds-form">
                        <div class="slds-form-element slds-form-element_horizontal">
                            <label class="slds-form-element__label" for="horizontal-input-id-01">Id</label>
                            <div class="slds-form-element__control">
                                <lightning:formattedText value="{!v.acccountInfo.Id}" />
                            </div>
                        </div>
                        <div class="slds-form-element slds-form-element_horizontal">
                            <label class="slds-form-element__label" for="horizontal-input-id-01">Name</label>
                            <div class="slds-form-element__control">
                                <lightning:formattedText value="{!v.acccountInfo.Name}" />
                            </div>
                        </div>
                        <div class="slds-form-element slds-form-element_horizontal">
                            <label class="slds-form-element__label" for="horizontal-input-id-01">BillingAddress</label>
                            <div class="slds-form-element__control">
                                <lightning:formattedText value="{!v.acccountInfo.BillingAddress.country}" />
                            </div>
                        </div>
                    </div>
                </fieldset>
            </div>
        </lightning:layoutItem>
    </lightning:layout>
</aura:component>	
```

######説明
　単純に初期化処理を実行して、取得した情報を画面で表示します。

---

######5. newtabController.js

```javascript:newtabController.js
({
    init : function(component, event, helper) {
        var pageReference = component.get("v.pageReference");
        var accountId = pageReference.state.c__accountId;
        var action = component.get("c.getAccountById");
        action.setParams({ accountId : accountId  });
        action.setCallback(this, function(response) {
            var state = response.getState();
            if (state === "SUCCESS") {
                console.log(response.getReturnValue());
                component.set("v.acccountInfo", response.getReturnValue());
            }
            else {
                console.log("Failed with state: " + state);
            }
        });
        // Send action off to be executed
        $A.enqueueAction(action);

    }
})
```

######説明
　PageReferrenceオブジェクトのstateから、親コンポーネントから渡されたパラメータを取得します。取得した取引先IDにより、apexコントローラーを呼び出し、必要な情報を取得し、画面の属性(acccountInfo)に設定します。<font color="red">**4**</font>のコンポーネントを正常に表示できます。

---

##動作確認

　体験版ソフトを使っているので、透かしは許してください
![show gif](https://media.giphy.com/media/kCDfK17gIxpWbQ3XbH/giphy.gif)

---

##参照
1. [Aura コンポーネントのため Lightning データサービスの基本](https://trailhead.salesforce.com/ja/content/learn/modules/lightning_data_service)
2. [Aura Component Record Data](https://developer.salesforce.com/docs/component-library/bundle/force:recordData/documentation)
3. [Navigate to Component Using lightning:navigation](https://rajvakati.com/2018/11/13/navigate-to-component-using-lightningnavigation/)
4. [Pass Parameter Using Lightning Navigation](https://salesforce.stackexchange.com/questions/274242/pass-parameter-using-lightning-navigation)
5. [Aura Component Navigation](https://developer.salesforce.com/docs/component-library/bundle/lightning:navigation/documentation)
6. [pageReference Types](https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/components_navigation_page_definitions.htm)