[Salesforce]画面フローで使える地図コンポーネントを作ってみた

## はじめに
昨今Salesforceではフローの進化が目覚ましく、どんどん使えるシーンが増えていっています。
画面フローを使えば、VisualforceやLightningコンポーネントのプログラミングの知識がなくとも、ポイント＆クリックで簡単に画面作成ができてしまいます。簡単に実装できるメリットがある反面、少し複雑な要件や凝ったUIを実現しようとすると難しくなる場合が多いです。AppExchange等でフローで利用できるコンポーネントが公開されていたりもしますが、微妙に機能がマッチしなかったり、UIの一環性がなかったりと適用をためらってしまうこともあるのではないかと思います。
「ないならば作ってしまえ」が今回のテーマになります。
本稿ではLightningWebComponent（以下LWC）で作成したカスタムコンポーネントを画面フローで利用する方法を紹介します。例としてフローで取得した住所情報を表示する地図コンポーネントを作っていきたいと思います。

## 今回のアプローチ方針
今回はなるべくコーディングする要素を減らし、シンプルに作っていきたいと思います。
この方針から以下の点を意識して実装していきたいと思います。
- 基本はフローベースで開発
- フローでは実装できない最低限の画面コンポーネントをLWCで開発する
- コーディングは最低限にとどめる（フローでできることはフローでやる）
- フローの開発スピードとLWCの自由度のおいしいところ取りをする

## デモアプリ
以下のようなアプリを作ってみたいと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878697/f47a15e8-89c5-f058-2d49-0b072e38604d.png)

住所情報というオブジェクトを作成します。
項目はローケーション名（Name項目）と住所のみです。住所項目はSummer'22でリリースされた住所型を利用しています。
ページの右側には住所項目の住所の地図が表示されています。
この地図コンポーネントが画面フロー＋LWCで作成されたコンポーネントになっています。

## 画面フローでLWCを利用する方法
まずはフロービルダーで使えるLWCの使い方です。
LWCをフローで参照できるようにするには、コンポーネント設定ファイルである```.js-meta.xml```ファイルに以下のような設定をする必要があります。

```xml:flowMap.js-meta.xml
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>55.0</apiVersion>
    <isExposed>true</isExposed>
    <masterLabel>Map Component In Flow</masterLabel>
    <targets>
        <target>lightning__FlowScreen</target>
    </targets>
    <targetConfigs>
        <targetConfig targets="lightning__FlowScreen">
            <property name="country" label="Country" type="String"/>
            <property name="state" label="State" type="String"/>
            <property name="city" label="City" type="String"/>
            <property name="street" label="Street" type="String"/>
            <property name="postalCode" label="PostalCode" type="String"/>
            <property name="zoomLevel" label="Zoom Level" type="Integer"/>
        </targetConfig>
    </targetConfigs>
</LightningComponentBundle>
```
- target
フローで利用できるようにするためにtargetに```lightning__FlowScreen```を指定します。
- targetConfig
この設定は任意です。フロービルダーから渡すパラメータを指定することができます。
ここでは地図コンポーネントに渡す住所情報（Country,State,City,Street,Postal Code）と地図の拡大率（Zoom Level）をパラメータとして指定しています。フローの場合、パラメータの型は以下がサポートされています。
 ・String
 ・Integer
 ・Boolean
 ・Date
 ・DateTime
 ・@salesforce/schema/namespace__Objectname（標準オブジェクトおよびカスタムオブジェクト）
 ・apex://namespace.Classname（Apexで定義したクラス）
 ・配列形式

## 地図コンポーネントの作成
地図コンポーネントのLWCのコードになります。

まずは画面のHTMLです。
LWC標準の```lightning-map```要素を配置しているのみのシンプルな構造です。
地図の位置情報を指定する```map-markers```属性と地図の拡大率を指定する```zoom-level```属性はjs側から渡します。
```html:flowMap.html
<template>
    <lightning-map 
        map-markers={mapMarkers} 
        zoom-level={zoomLevel}>
    </lightning-map>
</template>
```

続いてJavaScriptコードです。
フローから渡されるパラメータを持つ変数には```@api```デコレータを指定する必要があります。
```connectedCallback()```イベントの中でコンポーネントに渡す位置情報を生成しています。
LWC側で地図に表示する住所情報を取得してくることも可能ですが、今回はデータ取得はフローに移譲するため、そのようなロジックは含まれていません。

```javascript:flowMap.js
import {LightningElement, api} from 'lwc';
export default class FlowMap extends LightningElement {
    @api city;
    @api country;
    @api postalCode;
    @api state;
    @api street;
    @api zoomLevel;
    mapMarkers;

    connectedCallback() {
        // Mapコンポーネントに渡す位置情報を生成
        let mapMarkers = [
            {
                location: {
                    City: this.city, 
                    Country: this.country, 
                    PostalCode: this.postalCode, 
                    State: this.state, 
                    Street: this.street
                }
            }
        ]
        this.mapMarkers = mapMarkers;
    }
}
```

## 画面フロー設定
画面フローの設定は以下のようになっています。
<img width="200" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878697/0a03a328-982c-0fa2-e94f-11281a8a7209.png">

1. 住所情報取得
まずは地図に表示する住所情報のレコードを取得します。
フローの入力変数として定義した```recordId```を条件にレコードを取得します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878697/eb781089-c6bb-080a-e65c-23d39b1b4391.png)

2. 地図表示
地図を表示する画面です。
画面左のコンポーネントセクションから先程作成したLWCを画面に配置します。
1で取得した住所情報を地図コンポーネントのパラメータとして設定します。（City、Country、PostalCode、State、Street）
また地図の拡大率（Zoom Level）に任意の数字を入力します。デスクトップの場合は1～22が設定可能範囲になりますが、今回は入力チェック等は実装していません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878697/9477e8d2-9926-79a0-8639-18594c7a9f2a.png)

あとは作成したフローをLightningページに配置するだけです。
フローコンポーネントをページに配置し、先程作成したフローを指定します。
パラメータとなる```recordId```の設定は```レコードIDをこの変数に渡す```にチェックを入れてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878697/1f53e1cb-dcae-4e95-11ee-ec017b6aec06.png)

## 住所型項目利用時の注意点
住所型項目の国と都道府県は選択リストであり以下のような定義をします。
（※州コードで利用できるのは英数字のみです）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878697/3afe158d-a3c5-6831-b8ce-970ca809635a.png)
データベース上も州コード（API参照名）で保存されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878697/99fbfbb3-0fdc-2d56-25af-57a726e09f0b.png)
今回の例では都道府県として地図コンポーネントに渡しているのは州コード（ここでは「TOKYO」）です。
州コードが地図コンポーネントが都道府県と特定できないコード体系になっている場合は地図が正しく表示されない可能性があるので注意しましょう。必要に応じてフロー側でコード変換をする必要がでてきます。

## まとめ
今回は画面フローで使える地図コンポーネントをLWCで自作してみました。
今回の地図コンポーネントは住所情報をパラメータにし汎用的に作られているので、様々なユースケースで再利用もできると思います。
コーディングは最低限にとどめているので開発コストもフル個別開発よりは削減できます。
画面フロー標準では満たせないコンポーネントが必要になった際は、自作することも検討してみてはどうでしょうか？