Salesforce LWCで動的に選択リストを作る

# これは何？
この記事は「[24日後に立派なSalesforceエンジニアになるWEBエンジニア Advent Calendar 2022](https://qiita.com/advent-calendar/2022/kakakaori)」の15日目の記事です。10日後に立派なSalesforceエンジニアになるために今日からはLightning Web Component (LWC)で動的な選択リストを作ってみたいと思います。

# 何を作る？
[lightning-combobox](https://developer.salesforce.com/docs/component-library/bundle/lightning-combobox/example)を使うことで選択肢リストを作ることができる。サンプルでは以下のように選択肢を定義しているが、これだとメンテナンス性が悪いので、このように定義リストをコード内に書くのではなく、オブジェクトから動的にとってくるようにしたい。
```javascript:select.js
    get options() {
        return [
            { label: 'New', value: 'new' },
            { label: 'In Progress', value: 'inProgress' },
            { label: 'Finished', value: 'finished' },
        ];
    }
```
今回は例としてAccountオブジェクトにある「会社形態(Ownership)」という選択肢リストに登録されている選択肢をとってきて、comboboxの選択肢として動的に表示する。

# 完成したコンポーネントのイメージ
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200812/eba6480c-2846-ecec-1a5b-7d55f2436f79.png" width='200px'>

# 作り方
`@wire`デコレータを使うことでApexなしにオブジェクトから選択肢を取得してくることができる。
今回は[getPickListValues](https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.reference_wire_adapters_picklist_values)を使って選択リスト値を取得してこようと思うが、このメソッドを呼び出すためにはレコードタイプIDを指定する必要があるので、まずはレコードタイプIDの取得を行う。
レコードタイプIDは[getObjectInfo](https://developer.salesforce.com/docs/component-library/documentation/ja-jp/lwc/lwc.reference_wire_adapters_object_info)から取ってくる。[getObjectInfo](https://developer.salesforce.com/docs/component-library/documentation/ja-jp/lwc/lwc.reference_wire_adapters_object_info)のサンプルコードを参考に以下のようにレコードタイプ名を指定してレコードタイプIDを取得する。

```javascript:select.js
    @wire(getObjectInfo, { objectApiName: ACCOUNT_OBJECT})
    objectInfo({data, error}) {
        if(data) {
            const rtis = data.recordTypeInfos;
            this.recordTypeId = Object.keys(rtis).find(rti => rtis[rti].name === '取ってきたいレコードタイプ名');
        } else if(error) {
            console.log('error');
        } 
    }
```

これでレコードタイプIDが取ってこれたので`getPickListValues`に`recordTypeId`を渡して選択肢リストを取得する。

```javascript:select.js
    @wire(getPicklistValues, { recordTypeId: '$recordTypeId', fieldApiName: ACCOUNT_OWNERSHIP_FIELD })
    ownershipOptions;
```

これで選択肢リストが`ownershipOptions`に渡されるのであとはテンプレート側からcomboboxを呼び出すときに選択肢として指定する。`ownershipOptions.data.values`とすることで目的の配列が取得できる。また`ownershipOptions`が取得できる前にページを表示しようとするとエラーで落ちてしまうので`if:true={ownershipOptions.data}`を忘れずに。

```html:select.html
<div if:true={ownershipOptions.data} class="wrapper">
    <lightning-combobox
    label="会社形態"
    options={ownershipOptions.data.values}
    data-field-name="Ownership"
    onchange={handleOwnershipChange}
></lightning-combobox>
</div>
```

# まとめ
```javascript:select.js
import { LightningElement, wire } from "lwc";
import { getPicklistValues, getObjectInfo } from 'lightning/uiObjectInfoApi';
import ACCOUNT_OBJECT from '@salesforce/schema/Account';
import ACCOUNT_OWNERSHIP_FIELD from '@salesforce/schema/Account.Ownership';

export default class AccountSearch extends LightningElement {
    recordTypeId = null;

    @wire(getObjectInfo, { objectApiName: ACCOUNT_OBJECT})
    objectInfo({data, error}) {
        if(data) {
            const rtis = data.recordTypeInfos;
            this.recordTypeId = Object.keys(rtis).find(rti => rtis[rti].name === 'レコードタイプ名');
        } else if(error) {
            console.log('error');
        } 
    }

    @wire(getPicklistValues, { recordTypeId: '$recordTypeId', fieldApiName: ACCOUNT_OWNERSHIP_FIELD })
    ownershipOptions;
}
```

```html:select.html
<template>
    <lightning-card  title="動的選択肢リスト">
        <lightning-layout>
            <lightning-layout-item padding="around-small">
                <div if:true={ownershipOptions.data} class="wrapper">
                    <lightning-combobox
                    label="会社形態"
                    options={ownershipOptions.data.values}
                    data-field-name="Ownership"
                    onchange={handleOwnershipChange}
                ></lightning-combobox>
                </div>
            </lightning-layout-item>
        </lightning-layout>
    </lightning-card>
</template>
```
これでcomboboxの選択肢をオブジェクトの項目から動的に取ってくることができた！
ちなみにレコードタイプがデフォルトのもの以外に設定されていない時はもうちょっとシンプルでこれだけでOK。
```javascript:select.js
export default class AccountSearch extends LightningElement {
    @wire(getObjectInfo, { objectApiName: ACCOUNT_OBJECT })
    accountObjectInfo;

    @wire(getPicklistValues, { 
             recordTypeId: '$accountObjectInfo.data.defaultRecordTypeId', 
             fieldApiName: ACCOUNT_OWNERSHIP_FIELD })
    ownershipOptions;
}
```

# 最後に
今日はLightning Web Component (LWC)で動的な選択リストを作ってみました。自前で検索フォームとかを作る時にはとても役に立ちそう！
LWC関連は一旦ここまでにして、明日はVisualforceページについてみていこうと思います。