📝

microCMSのカスタムフィールドを駆使してエディター機能を拡張する

2021/02/26に公開

microCMSを導入する機会がここ一年でとても増えたのですが、少し複雑な動的要素を必要とする場面では用意されているリッチエディタなどの機能では実現が難しい場合があります。
今回はmicroCMS公式ブログの『リッチエディタを使いつつ一部はHTMLで入稿する』という記事を参考にHTMLだけではなく様々な要素をエディタで実現したので紹介します。

実現したいこと

例えば

  • ソースコードのシンタックスハイライト機能(参考:Qiita
    Qiitaのシンタックスハイライト

  • 吹き出し風の対話UI(参考:TechAcademy
    TechAcademyの吹き出し風対話UI

考えればキリがありませんがパッと思いつくところでは上記のようなものをメディアサイトなどでよく見かける気がします。
前述のmicroCMS公式の記事に沿ってCMS上でHTMLをそのまま書いてしまえば実現自体は可能なのですが、CMSの更新は非エンジニアの方が担当する場面も多いと思いますし、仮に開発者が入力する場合もミスの元となりますので現実的ではないです。

シンタックスハイライトに関してはリッチエディタにも『コードブロック』という装飾ボタンがあり、吐き出されるHTMLが<code>で括られるので問題ないようにも思えますが、Qiitaのようにコードブロックにファイル名(index.jsなど)を表示しようと考えると途端に実現が困難になります。

そのような複雑なUIを実装したい場合、今回の手法が役に立つはずです。

情報の整理

今回は例として吹き出し風対話UIを作ってみます。
必要な入力情報として下記を設定しようと思います。

  • 画像
  • 名前
  • 方向
  • 内容

最低限これらが設定できれば問題ないでしょうか。

microCMSで設定できるコンテンツの種類はざっくり下記になっています。

機能名 概要
テキストフィールド 自由入力の1行テキスト 文字列
テキストエリア 自由入力の複数行テキスト 文字列
リッチエディタ 自由入力の複数行テキスト HTML文字列
画像 画像用のフィールド(imgix対応) URL、width、height
日時 Date型フィールド。カレンダーから選択 ISO 8601形式
真偽値 スイッチのOn/Off 真偽値
セレクトフィールド 定義したリストから値を選択 文字列
コンテンツ参照 他コンテンツの参照 コンテンツ内容
複数コンテンツ参照 他コンテンツの複数参照 コンテンツ内容の配列
数字 数字 数字
カスタム 別途定義したカスタムフィールドを入力 カスタムフィールド
繰り返し 別途定義したカスタムフィールドを複数入力 カスタムフィールドの配列

※上記は2021年2月時点でmicroCMSのHobbyプラン(無料)で設定できる項目です。

先ほど挙げた項目をそれぞれmicroCMSのどの種類の項目で作れば良いかを考えていきます。

  • 画像:画像
  • 名前:テキストフィールド
  • 方向:セレクトフィールド(右or左)
  • 内容:テキストエリア

これらをmicroCMSのカスタムフィールドに設定します。

カスタムフィールドの作成

冒頭のmicroCMS公式の記事と内容が被ってしまいますが一応手順を載せておきます。
適当なAPIにカスタムフィールドを作成します。

前項で挙げた必要な項目をそれぞれ設定します。

『direction』のセレクトフィールドは『left』、『right』を選択肢として設定しました。

カラムは完成形のUIに近い配置でこのように設定してみました。

テキストなどで使うので同じ手順でリッチエディタのみ入力できるカスタムフィールドも追加しておきましょう。

記事の作成

先ほど作成したカスタムフィールドに紐づくAPIの設定を変更します。
今回『タイトル』、『内容』のみのシンプルなAPIを作りました。

上記画像内、表示名『内容』の項目のフィールド種類を『繰り返し』に変更します。

先ほど作成したカスタムフィールドが選択肢として表示されるので全部にチェックを入れて設定完了。記事を作り『内容』の項目を設定しようとするとこんな感じでどのカスタムフィールドを使用するか選択できるようになります。

リッチエディタを選んで従来通りの文章も入力できますし、文章の途中で吹き出し風対話UIを挟むこともできます。
とりあえずリッチエディタを使ったテキストと吹き出しの左右を作ってみて実際に取得できるJSONを見てみると下記のようになります。

{
    "id": "your_id",
    "createdAt": "2021-01-01T01:01:00.000Z",
    "updatedAt": "2021-01-01T01:01:00.000Z",
    "publishedAt": "2021-01-01T01:01:00.000Z",
    "revisedAt": "2021-01-01T01:01:00.000Z",
    "title": "Zennテスト記事",
    "content": [
        {
            "fieldId": "richEditor",
            "editor": "<p>リッチエディタでテキストを記述する</p>"
        },
        {
            "fieldId": "balloon",
            "image": {
                "url": "https://images.microcms-assets.io/assets/abcd0123/abcd0123/img-01.png",
                "height": 800,
                "width": 749
            },
            "name": "狼っぽいの",
            "direction": [
                "left"
            ],
            "text": "俺は狼っぽい何かだぞ!"
        },
        {
            "fieldId": "balloon",
            "image": {
                "url": "https://images.microcms-assets.io/assets/abcd0123/abcd0123/img-02.png",
                "height": 800,
                "width": 695
            },
            "name": "凛々しい雪だるま",
            "direction": [
                "right"
            ],
            "text": "そうなんですね。犬かと思いました。"
        }
    ]
}

contentの内容がそれぞれのカスタムフィールドの配列になりました。
fieldIdで配列の値がどのカスタムフィールドなのかが判断できるので、これを元に実装します。

フロントエンドでの実装

今回はReactを例に実装します。microCMSから情報を取得する手順は省略。
fieldIdの値で分岐して表示する内容を変更します。

const App = () => {
  // 前項に記載したmicroCMSから取得できるデータ
  const articleData = fetchData()

  return (
    <div className="contents-area">
      {articleData.content.map((customField) => {
        switch (customField.fieldId) {
          case 'richEditor':
            return (
              <p
                key={customField.fieldId}
                dangerouslySetInnerHTML={{
                  __html: customField.editor
                }}
              />
            )
          case 'balloon':
            const image = customField.image
            return (
              <div
                key={customField.fieldId}
                className={`balloon--${customField.direction}`}
              >
                <figure className="balloon__image">
                  <img
                    src={image.url}
                    alt=""
                    width={image.width}
                    height={image.height}
                  />
                  <figcaption>{customField.name}</figcaption>
                </figure>
                <p>{customField.text}</p>
              </div>
            )
        }
      })}
    </div>
  )
}

スタイルとかを軽く整えたらこんな感じになりました。

このようにさまざまなカスタムフィールドを作成することでリッチエディタでは表現できない複雑なUIに関しても細かく値を定義して作成できます。ちょっと手間ではありますが、microCMSで要件が複雑な場合はこのような方法を試してみてはいかがでしょうか。

Discussion