LightningComponentの歩き方と、画面遷移にまつわるTips

# はじめに

[Salesforce Platform Advent Calendar 2017](https://qiita.com/advent-calendar/2017/salesforce-platform) 13日目ですねー。フレクト4連続投稿2日目です。
前日の記事はNomadBlackyさんの[ざっくりおぼえる sfdx コマンド](https://qiita.com/NomadBlacky/items/d4150529108d6943a12b)でした。

2017年を振り返ると、主にこんな技術を実案件に導入しました。

- Push Upgrade
- LightningComponent SPA開発
- Salesforce DX

DXも慣れてきたので来年はAppExchange組織にDevHubを入れたいです。DevHubとPushUpgrade組み合わせたらおはようからおやすみまでCI/CDできるので最強だと思ってます。

# LightningComponentの歩き方

## リファレンス

構築するには、まずはリファレンス…ということで開発者ガイド。

https://developer.salesforce.com/docs/atlas.ja-jp.lightning.meta/lightning

Salesforceはドキュメントが豊富なプラットフォームですが、リファレンスに加えてStepByStepで学べるガイドが付録として用意されているのが良いところです。いまでこそTrailheadが役を担っていますが、開発者ガイドも今なお初心者にとっての最適な学習資料だと思ってます。

Salesforceの公式イベントに参加すると開発者ガイドの製本版がもらえることがありますが、
リリースの度にたくさんAPIが増え続けているので、最新情報はWeb版+リリースノートを参照すると良いでしょう。

## ざっくり概要とサンプルを知りたい

もう少し概要から知りたい、という方は @mokamoto さんのWebinar資料から。

https://developer.salesforce.com/events/webinars/LightningComponents_Dev_0426

@isanuki さんも[5日目](https://qiita.com/isanuki/items/51f76c578f8a39bc53e5)でおっしゃっていますが、Lightningといってもサービスや機能は多岐に渡ります。こちらのWebinarは「そもそもLightningComponentって全体のどういう位置付けだっけ？」という復習をするにはもってこいです。
LightningContainer, DataService, LightningOutはまだまだ情報が少ないながらも、しっかり触れられているのが良いですね。

実装例としては稲葉さん達のWebinarも参考になります。法人インフォのことは正直知らなかった。
https://developer.salesforce.com/events/webinars/lightning_components_tips_0712

## Trailheadで学ぶ

まずは一通り慣れてみたい場合は、TrailheadでLightningComponentの主要な使い方は網羅されているので、Trailheadに沿って勉強していくのが良いでしょう。
以下のTrailmixは、LightningExperienceとは、から学ぶことができるのでオススメ。

[Learn Lightning Component Development Faster](https://trailhead.salesforce.com/ja/users/005500000060ZGNAA2/trailmixes/learn-lightning-component-development-faster)

内容が被ってしまっていますが、自分でも今年LightningComponentでの本格的な開発をやったときには、プロジェクト用のTrailmixを作ってみたりしました。Trailmixは主にプロジェクト開始前のチームスキルUPに最適ですね。

[Lightningコンポーネントのきほん](https://trailhead.salesforce.com/ja/users/00550000006blQZAAY/trailmixes/basic-of-lightning-component)

Superbadgeもあります。
https://trailhead.salesforce.com/ja/super_badges/superbadge_lcf

そろそろSFDUGルーキー会のお題として取り上げてみたいと思いますので、
楽しくわいわい学んでみたい方はぜひ　[Trailbrazerコミュニティ](https://success.salesforce.com/_ui/core/chatter/groups/GroupProfilePage?g=0F93A000000HTtr) のグループページからどうぞ（唐突な宣伝）。

# LightningComponent Tips

今年一番ハマったやつを一つだけ…

## LightningComponentで画面遷移

基本的にLightningComponentはパーツ単位で作り、コンポーネント間で複雑な連携はしない、
疎結合なUIの仕組みだと捉えています。なので、あまりコンポーネント間で画面遷移するような
開発をすることはないのですが、それでも必要になるケースがあります。

ざっくりこんな感じの画面遷移をしようとしていて、Component->Componentへの遷移が必要でありました。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/87979/32dc43ac-5e55-f993-c86a-7423ad556f7c.png)

15-16ページくらいのLightningComponentで作られた画面群があり、各画面に5-10個程度存在するコンポーネントに含まれるUIアクションで別画面へ遷移していくイメージ。

### 1. window.location.href で遷移させる

```js
    goToNextPage : function(cmp,event,name) {
        var url = window.location.href;
    ...
```

一番無難な方法です。これの弱点は一度画面全体を再読込する形になるため、
LightningExperienceで普通に使うと画面のローディングコストがかかります。
これはSalesforceアプリでも同様ですね。
AndroidでいうとActivityが切り替わるようなイメージ。

### 2. navigateToComponent

navigateToComponentは、Lightningコンポーネントから別のコンポーネントに移動するためのAPIです。

https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/ref_force_navigateToComponent.htm


```js
navigateToMyComponent : function(component, event, helper) {
    var evt = $A.get("e.force:navigateToComponent");
    evt.setParams({
        componentDef : "c:myComponent",
        componentAttributes: {
            contactName : component.get("v.contact.Name")
        }
    });
    evt.fire();
}
```

コンポーネント名を指定するだけで良く、かつ画面全体の読み込みは入らないので使い勝手が良いです。
ただし2017/12/12時点でBeta版であり、これを使うと次コンポーネントを含む画面のスクロールができなくなるという
問題がありました。

force:navigateToComponent is not working
https://developer.salesforce.com/forums/?id=9060G000000I2BtQAK

WorkAroundとしては、対象コンポーネントを `ui:scrollerWrapper` でラップすることで
擬似的にスクロール可能にするというもの。

Account.cmp

```html

<aura:component>
    <aura:attribute name="accountId" type="Id"/>
    <ui:scrollerWrapper class="outerScroller">
	    <c:AccountContainer accountId="{!v.accountId}"/>
    </ui:scrollerWrapper>
</aura:component>
```

Account.css

```css
.THIS.outerScroller {
    height: 100%; 
    width: 100%;
    border-radius: 1px;
}
```

上の解決策では確かに対象コンポーネントのスクロールは可能になるのですが、局所的な解決であり、パッチワーク的です。また、致命的なことに、Salesforceアプリのレコードページのスワイプアクション「Pull to refresh」などが使えません。

### 3. ということでタブ経由で遷移させる

navigateToUrlであればスクロール問題は発生しないため、解決策としては
「次の画面をタブとして登録し、タブのURLを遷移先とする」。

```js

    gotoComponentViaTab : function(tabDef, attributes) {
        var urlEvent = $A.get("e.force:navigateToURL");
        urlEvent.setParams({
            "url": "#/n/"+ tabDef +"?id=" + attributes.accountId
        });
        urlEvent.fire();
    },
```

Componentに `force:appHostable` インタフェースを実装させると、Lightningページだけでなく、LightningComponentもSalesforceのカスタムタブとして登録できます。

タブのURLを指定することで、一旦WorkAroundとしての画面遷移ができるようになりました。

### とはいえ

保守性や効率性を考慮して、基本的にはLightningComponentはシンプルに使えるように要件をまとめるのが戦略です。

それでも…ということであれば、端的に画面遷移を複雑に必要とするようなケースでは、
ReactやVue.jsなどルーティングが得意なライブラリをラップしたコンポーネントにしてあげるのがおすすめですね。

このあたりを参考に
https://qiita.com/mino0123/items/eb350267121c27dd9322
https://github.com/zaki-yama/react-lightning-component-template

もしくは倉谷さんのこれも参考に
https://qiita.com/a_kuratani/items/75947a62b98f38af86f7

# 終わりに

書いてみたら量が多くなってしまったので一旦続きは別記事にしたいと思います。
VisualforceとLightningComponentが要件に応じて取捨選択できるようになったことで、構築上の選択肢は広がりましたし、AppExchangeでの配布やLightningExperienceの柔軟かつ簡易な画面設計を実現するためには欠かせない存在ですので、LightningComponentをSalesforce BaseSkillとして抑えておくと良いと思います。

次は G-Fさんの「SFのAPIとAWSのServerlessなAPIを連携させた話」です！