【Salesforce】Lightningページに画像を表示する方法まとめ

# はじめに
Salesforceでページに画像を配置・表示する方法は様々あります。
それぞれの実装方法とメリット・デメリットをまとめました。

# ユースケース
商品オブジェクトに商品画像のリンクとなるURLを指定する「商品画像URL」（ProductImageURL__c）という項目があったとします。
「このURLに指定した画像をLightningページに表示したい」
という要件があったケースを想定します。

# 実装パターン
今回は以下のような実装方法を説明します。
それぞれメリット・デメリットがあるので、要件に合わせて適切な方法を選択してください。
|コンポーネント|レコード項目の参照|画像の可変表示|ファイルの配置場所|リストビューでの表示|デザインの自由性|ビジネスロジックの追加|実装コスト
|:--|:--|:--|:--|:--|:--|:--|:--|
|[方法①：数式項目での実装（IMAGE関数の利用）](#方法数式項目での実装image関数の利用)|〇|可能|任意<br>（URLで公開可能な場所）|可能|×<br>（画像サイズ＋ページレイアウトのみ）|△<br>（数式で可能な範囲）|小
|[方法②：数式項目＋動的フォームでの実装](#方法数式項目動的フォームでの実装方法の拡張)|〇|可能|任意<br>（URLで公開可能な場所）|可能|×<br>（画像サイズ＋ページ内配置のみ）|△<br>（数式で可能な範囲）|小
|[方法③：リッチテキストコンポーネントでの実装](#方法リッチテキストコンポーネントでの実装)|×|不可|任意<br>（URLで公開可能な場所））|不可|△<br>（リッチテキストで実現可能な範囲）|×|小
|[方法④：画面フローでの実装](#方法画面フローでの実装)|△<br>（画像コンポーネントへの直接指定は不可）|一部可能|静的リソース|不可|△<br>（画面フローで実現可能な範囲）|〇<br>（画面フローで実現可能な範囲）|中
|[方法⑤：LightnigWebコンポーネントでの実装](#方法lightnigwebコンポーネントでの実装)|〇|可能|任意|不可|〇<br>（HTML、CSSで自由に実装可）|〇<br>（JS、Apexで自由に実装可）|大



# 方法①：数式項目での実装（IMAGE関数の利用）
オブジェクトマネージャーで対象のオブジェクトのカスタム項目を作成します。
データ型は数式を選択します。数式の戻り値のデータ型は「テキスト」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878697/4029b1ba-cdd3-4a24-ce3b-c37c2da036d5.png)
数式エディタで以下のように設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878697/3c9cca60-08c0-2bc8-fadf-31ac3d37c788.png)
```IMAGE(画像URL, 代替テキスト, 高さサイズ, 幅サイズ)```関数を使って表示する画像を設定します。
高さと幅は任意設定なので指定しなくてもOKです。その場合は元の画像のサイズのまま表示されます。
対象項目をページレイアウトに追加すれば設定は完了です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878697/d2dc6968-03db-ebcd-9181-d99f89654f30.png)
カスタム項目として定義しているので、リストビューでも画像を表示できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878697/b76618db-d45b-dee9-4423-6148e746726c.png)

#### メリット
- オブジェクトの一項目として画像を表示できる。
- リストビューにも画像を表示できる。
- 数式を活かしたカスタマイズが可能（例えば画像URLが設定されていないときは代わりにテキストを表示するといったことが可能）
#### デメリット
- 画像サイズが大きい場合に項目の高さが大きくなりスクロールが発生する。
- IMAGE関数の画像サイズ指定は高さ幅の両方を指定する必要がある。（画像が可変に変わる場合、元の画像のアスペクト比が維持できない）

# 方法②：数式項目＋動的フォームでの実装（方法①の拡張）
方法①だとページレイアウトの一項目として画像が表示されます。ページレイアウトに入れるのではなく、独立した場所に画像を表示したい場合は動的フォームを利用することで実現可能です。
Lightnigアプリケーションビルダーでページを編集します。画像表示専用のコンポーネントとして「レコードの詳細」を配置します。（項目表示するコンポーネントとは別に新規追加します）
レコードの詳細コンポーネントを選択し「アップグレードに関するお問い合せ」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878697/47d74254-023c-761c-112b-fe529b450044.png)
ウィザードに従って動的フォームを有効化します。
ページレイアウトの選択では画像項目が含まれるページレイアウトを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878697/9ea0c59c-6c09-c720-628c-a37838347d25.png)
通常の項目表示用のレコードの詳細コンポーネントでは商品画像が表示されないように、商品画像項目をレイアウトから削除します。
商品画像表示用のレコードの詳細コンポーネントでは画像項目のみを残します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878697/a35b5cda-c414-8ce9-f7fd-94c0c8d4d579.png)
左：レコード項目表示用のレコードの詳細コンポーネント
右：画像項目表示用のレコードの詳細コンポーネント

保存、有効化してページを見ると、以下のように商品画像項目だけが独立して表示されるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878697/d9e23ff7-2984-77f8-e845-202dff4aefc7.png)

#### メリット
- その他の項目とは独立した配置で画像が表示できる。
- 項目表示用のレイアウトから画像項目がなくなり、すっきりとした印象となる。（画像サイズによるスクロール発生も抑制できる）
#### デメリット
- 動的フォームでの管理が必要となるため、設定が少し煩雑になる。

# 方法③：リッチテキストコンポーネントでの実装
アプリケーションビルダーで利用できる標準コンポーネントとしてリッチテキストコンポーネントがあります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878697/6a895498-c5cb-ef93-c8fa-97bb44d397f0.png)
アプリケーションビルダー上でリッチテキストコンポーネントを追加しエディタを表示します。
このリッチテキストエディタには画像を挿入するインターフェースはありませんが、画像を貼り付けることができます。特定の画像を右クリックし「画像をコピー」を選択します。ここではSalesforce上のファイル機能にアップロードした画像から実施していますが、ローカルのファイルでも同様の操作ができます。（自動的にSalesforce上にアップロードされます）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878697/b13a8ba4-c62e-03ee-867e-5902baeb29cc.png)
画像がコピーできたらリッチテキストエディタ上で貼り付けを実施します。（ctrl+vでも可）
エディタ上に画像が挿入されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878697/b95b2e95-4c4c-5016-c95a-84a760834202.png)
保存しページに戻ると以下のように画像が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878697/69f9c60a-a981-f2a8-efe7-481fe5252e22.png)
この方法の場合、画像の表示は簡単にできますがレコードの項目を参照することができないので、固定画像しか表示できません。したがってすべてのレコードにおいて同じ画像が表示されます。簡単に画像が表示できますがレコードに設定された画像URL項目の画像を設定することができないので、今回のユースケースの要件を満たすには不十分です。

#### メリット
- 標準コンポーネントが利用できるため、どの環境でもすぐに設定できる。
- リッチテキストで実装するため、画像と一緒に商品説明などの文章を入れることも可能。
#### デメリット
- レコードの項目値を参照できないため、可変に画像を表示することができない。
- 画像サイズの変更ができない。

# 方法④：画面フローでの実装
画面開発をローコードで実装できるツールとしてフローがあります。画面フローを使っても画像を表示することができます。
事前準備として静的リソース上に画像をアップロードしておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878697/937508fe-46e5-6b62-d896-814ac5205a48.png)
フロービルダーから画面フローを新規作成します。画面を追加しコンポーネント一覧から「表示画像」を追加します。
画面右側の設定の「画像名」に静的リソース名の名前を指定します。（ここでは「ProductImage1」）
フローを保存し有効化しておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878697/e6fe2c8e-3c1e-11b7-ad31-ae1c393009b1.png)
アプリケーションビルダーに戻り、ページにフローコンポーネントを追加し先程作成したフローを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878697/97271972-6cda-d009-7be5-f52f3ceaad5e.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878697/2033066e-8249-2d7d-bffe-5d6bc7071f63.png)
これでページに画像が表示されるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878697/503685cd-90ad-d923-c8fa-237bf8e0b7d2.png)
このケースでは画像の配置場所が静的リソースに限定されるため、方法③と同様にレコードの画像URL項目を使った可変表示はできません。ただしフローでの実装となるため、フロー内で処理を分岐させればある程度の可変表示を実現することもできます。使用する画像のパターンが数パータンであれば、この方法も使えると思います。
#### メリット
- 画面フローで実装するため、ビジネスロジックを加えた上で画像表示することが可能。（ある程度の画像表示の分岐が実現できる）
#### デメリット
- ファイルの配置場所が静的リソースに限定される。
- レコードの項目値を参照し可変に画像を表示するには不向き。

# 方法⑤：LightnigWebコンポーネントでの実装
方法①～④で実現できないような複雑な要件が必要とされる場合は、個別開発を検討する必要がでてきます。
今回はサンプルとしてLightnigWebコンポーネントを利用した画像表示コンポーネントのサンプルを紹介します。
画像を表示するだけのシンプルな構成で、アプリケーションビルダーから画像サイズ（高さ、幅）を指定できるようにしています。この他必要となるビジネスロジックは要件に合わせて適当に追加してください。
```xml:imageViewer.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>
    <targets>
        <target>lightning__RecordPage</target>
    </targets>    
    <targetConfigs>
        <targetConfig targets="lightning__RecordPage">
            <objects>
                <object>Product__c</object>
            </objects>        
            <property name="height" label="高さ" type="Integer"/>
            <property name="width" label="幅" type="Integer"/>
        </targetConfig>
    </targetConfigs>
</LightningComponentBundle>
```
```html:imageViewer.html
<template>
    <lightning-card title="商品画像">
        <image src={imageUrl} height={height} width={width}></image>
    </lightning-card>
</template>
```
```JavaScript:imageViewer.js
import { LightningElement, api, track, wire } from 'lwc';
import { getRecord, getFieldValue } from 'lightning/uiRecordApi';
import PRODUCT_OBJECT from '@salesforce/schema/Product__c';
import IMAGEURL_FIELD from '@salesforce/schema/Product__c.ProductImageURL__c';
const fields = [IMAGEURL_FIELD];
export default class ImageViewer extends LightningElement {
    @api
    recordId;
    @api
    height;
    @api
    width;
    @wire(getRecord, { recordId: '$recordId', fields } )    
    record;
    get imageUrl() {
        const val = getFieldValue(this.record.data, IMAGEURL_FIELD);
        return val;
    }
}
```
Lightningページに配置すると以下のように表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878697/05ed7676-31bc-2055-e16f-f9fc56a3e7fe.png)

#### メリット
- デザインやロジックなど要件に合わせて自由にカスタマイズできる。
#### デメリット
- 個別開発が必要なため、実装コストが大きい。


# まとめ
今回はSalesforceのページに画像を表示する方法をまとめました。
要件によって最適な実装方法が変わるため、ベストな選択をするための参考になれば幸いです。
新たなパターンがあれば追記してきたいと思います。