Shopifyでの動的セクションの作り方
こんにちは。
実務でShopifyを触る際に動的セクションを作ることがあるのですが、やり方を逐一調べていたので、この機会に改めて復習してみました。
簡単にではありますが、備忘録としてその流れについて綴りたいと思います。
(すでにテーマカスタマイズができる環境があることを前提とします。)
大まかな手順
-
XXX.liqiud
のようなLiquidファイルを作成する。 - 1で作成したファイルに
{% schema %} {% endschema %}
タグを記述する。- 必要であれば、ブロックを作成する。
- schemaタグ以外でのテンプレート側で内容を出力する処理を書く。
実装
schemaタグ
テーマテンプレート直下「sections」ディレクトリにて新たにXXX.liquid
のようなファイルを作成します。(ファイル名は任意)
作成後、ファイル内にschema
タグの中身を書いていきます。
動的セクションを作る上で、schema
タグ内の記述は必要不可欠です。
(scehma
タグの中に書くコードは原則、JSONで書きます。)
{% schema %}
{
"name": "新規セクション",
"settings": [
{
"type": "text",
"id": "title",
"label": "見出し",
"default":"テキストが入ります。"
}],
"presets":[
{
"name": "新規セクション"
}
]
}
{% endschema %}
-
name
:追加したいセクションの名前を定義します。 -
settings
:カスタマイズ画面にて、セクションの内容をノーコードで変更できるようにするために必要な要素になります。-
type
:反映したい内容の種類を定義します。(text
では、input
フォームにて簡単なテキスト内容を変更可能にします。) -
id
:テンプレート側で実際に出力する際に、必要になります。 -
label
:セクションを開いたときに詳細の内容にて、その値がどういったものであるのかを文字列で添えることができます。 -
default
:デフォルトで入れておきたい値を指定します。
-
-
presets
:動的セクションを追加したい際に必須になります。-
schema
タグトップのname
と値を同一にします。(ここでいうと新規セクション
の文字列が該当)
-
▶︎ liquidファイルにて上記の内容を書くと、ストアカスタマイズ画面 > セクションを追加
より、上で実装した内容でセクションが差し込めるようになっていると思います。
値を出力する
カスタマイズ画面では値を自由に変えられるようになったものの、まだ画面には何も内容が表示されないので、テンプレート側の内容を記述します。
schemaタグの上部に下記内容を記します。
<section class="new-section">
<h2>{{section.settings.title}}</h2>
</section>
{{section.settings.title}}
とすることで動的な値を画面に出力することができるようになります。
▶︎ schema
タグの中で記述した、id値を指定することがキモです。
上記のコードを書くと下記のようになっていると思います。
現時点での全てのコード内容は下記の通りです。
<section class="new-section">
<h2>{{section.settings.title}}</h2>
</section>
{% schema %}
{
"name": "新規セクション",
"settings": [
{
"type": "text",
"id": "title",
"label": "見出し",
"default":"テキストが入ります。"
}],
"presets":[
{
"name": "新規セクション"
}
]
}
{% endschema %}
ブロック制御(定義)
動的セクションを追加することができました。
続けて「セクションを追加」を選択することで追加したい数だけ、セクションを追加することができます。
しかしながら現状のままではいまいち実用性に欠けるので、ブロックによるコンテンツ出力に関して深掘りしていきたいと思います。
ブロックとは、前述で実装したようなセクションパーツを特定のコンテンツ内のみで、柔軟に扱えるようにした固有のコンテンツパーツになります。
▶︎ よくあるカードコンポーネントのような複数の要素を持ち合わせたパーツを作る際に有用です。
▶︎ 同じコンテンツ同士でも内容違いのものをそれぞれ出力したりする際に有用です。
前述でのコードを下記にて編集します。
...
{% schema %}
{
"name": "サンプルコレクション",
"settings": [
{
"type": "text",
"id": "title",
"label": "見出し",
"default":"テキストが入ります。"
}],
"blocks":[
{
"type": "collection_item",
"name": "画像",
"settings": [
{
"type": "image_picker",
"id": "image",
"label": "画像を追加してください"
},
{
"type": "text",
"id": "caption",
"label": "内容を記入してください",
"default": "本文が入ります。本文が入ります。本文が入ります。"
}
]
}
],
"presets":[
{
"name": "サンプルコレクション"
}
]
}
{% endschema %}
-
settings
属性に続き、新たにblocks
属性を追記します。- blocksにはsettingsと同様に、
type
、name
、settings
を記述します。-
type
:settings
の時とは違い、任意の文字列を指定することができます。- Liquid 内でブロックタイプ属性を元に条件判定を行うときなどに有用です。
-
name
:ブロックの名称を設定します。 -
settings
:そのブロックがどういった値を入れるものであるかを定義します。-
settings
と同じ要領で内容を書きます。(今回は画像を出力する際に使うimage_picker
とtext
タイプを使用しました。)
-
-
- blocksにはsettingsと同様に、
上記のコードによって、カスタマイズ画面にて、セクションの中にさらにコンテンツを追加できるようなUIが見られるようになったかと思います。
▶︎ 「画像を追加」を選択すると、新たに「画像」ブロックを追加することができるようになります。
この画像を追加というセクションのようなものが今回追加された「ブロック」になります。
ブロック制御(出力)
上で定義した内容をLiquidファイルにて出力します。
実際のコードが下記になります。
<section class="collection-section">
<h2>{{section.settings.title}}</h2>
{% if section.blocks != blank %}
<ul style="margin:0; padding:0; display: grid; grid-template-columns: repeat(3,1fr); gap:24px;">
{% for block in section.blocks %}
<li style="list-style: none;">
<img style="max-width: 100%; height:auto;" src="{{ block.settings.image | img_url: 'master'}}" alt="">
{% if block.settings.caption != blank %}
<span>{{block.settings.caption}}</span>
{% endif %}
</li>
{% endfor %}
</ul>
{% endif %}
</section>
...
【ポイント】
- ブロックで設定した内容は
section.blocks
配列にて個々の値が入るため、配列を展開して、値を出力していく作業が必要になります。
Liquidではfor文を使って値を展開することができるので、その方法を使います。
{% for block in section.blocks %}
▶︎ 必ず {% endfor %}
をお忘れなく。
-
単一の値を展開できたら、
block.settings.id名
で取り出したい値を出力できます。- 今回のように画像を扱う際には src値の後ろに
img_url
という感じにサイズの指定をする必要があるので注意です。
- 今回のように画像を扱う際には src値の後ろに
-
もし値が空の場合にそのタグ自体を出力しないようにしたいため、if文でその値が入っていた場合のみタグを出力するようにしています。
上記のコードにてコンテンツをブロック出力できるようになりました。
任意にブロックを追加していくことで下記のようにブロックを追加できるようになったのではないでしょうか。
※画像は実装イメージです。
※CSSは今回内容とは逸れるので、詳細は割愛させていただきます。
今回は、簡単に3カラムで表示できるようなギャラリーセクションを作りました。
ブロックで制御することで、画像下部にあるテキストのように要素間での微妙な内容の違いを表現することができるようになります。(例:販売中/売り切れ)
現時点での全てのコード内容は下記の通りです。
<section class="grid-section">
<h2>{{section.settings.title}}</h2>
{% if section.blocks != blank %}
<ul style="margin:0; padding:0; display: grid; grid-template-columns: repeat(3,1fr); gap:24px;">
{% for block in section.blocks %}
<li style="list-style: none;">
{% if block.settings.image != blank %}
<img style="max-width: 100%; height:auto;" src="{{ block.settings.image | img_url: 'master'}}" alt="">
{% endif %}
{% if block.settings.caption != blank %}
<span>{{block.settings.caption}}</span>
{% endif %}
</li>
<p>{{block.settings.desc}}</p>
{% endfor %}
</ul>
{% endif %}
</section>
{% schema %}
{
"name": "サンプルコレクション",
"settings": [
{
"type": "text",
"id": "title",
"label": "見出し",
"default":"テキストが入ります。"
}],
"blocks":[
{
"type": "grid_item",
"name": "画像",
"settings": [
{
"type": "image_picker",
"id": "image",
"label": "画像を追加してください"
},
{
"type": "text",
"id": "caption",
"label": "内容を記入してください",
"default": "本文が入ります。本文が入ります。本文が入ります。"
}
]
}
],
"presets":[
{
"name": "サンプルコレクション"
}
]
}
{% endschema %}
その他
schemaタグにあるpresets
属性では、他にも下記のような使い方ができます。
"presets":[
{
"name": "サンプルコレクション",
"settings": {
"title": "デフォルトテキスト"
},
"blocks": [
{
"type": "grid_item"
},
{
"type": "grid_item"
},
{
"type": "grid_item"
}
]
}
]
-
settings
:settings
属性で定義したidの値のデフォルト値を設定できます。-
settings
属性で指定したidと同一のものを指定します。
-
-
blocks
: セクションを追加した際にデフォルトで展開されるブロックの内容です。-
type
にはblocks
属性で指定した:id
と同一の値を設定します。 - 上記の例では、上の動的セクションを追加した際にデフォルトで3つのブロックが展開された状態で表示されるということになります。
-
settings等で出てきたtype
キーは今回使用したtext
、image_picker
以外にもたくさんの種類があります。詳しくはこちら
拙い内容ではありましたが、少しでも他の方のお力になれれば幸いです!!
参考
Discussion