2020-12-10

Sprig プラグインを使って reactive な Twig のコンポーネントを組み込む #craftcms

20201209 1011

これは Craft CMS Advent Calendar 2020 10日目の記事です。

JSを書けば出来るのはイメージが出来るのだけど、 Sprig プラグインを使うと reactive な twig の component をつくってユーザーのイベントにあわせて表示を変えることが出来る。
(reactive にいい日本語が思いつかない)

Sprig – A reactive Twig component framework for Craft.
https://putyourlightson.com/pl...

使われてるのはこの辺の htmx ってのもある様子。

</> htmx - high power tools for html
https://htmx.org/

初めて知った。
Alpine.js が近いのかなぁというきもしつつ。

alpinejs/alpine: A rugged, minimal framework for composing JavaScript behavior in your markup.
https://github.com/alpinejs/al...

近からず遠からずなんだろうか。 
Alpine.js の方はまた時間見つけて触ってみたい。

プラグインをインストール

Craftのディレクトリでcomposerで追加する。

composer require putyourlightson/craft-sprig

管理画面からプラグインを有効にする。

プラグインをインストールするとこんな感じで管理画面上で試すことも出来る。

20201209 1010

検索フォーム

Cookbook にいくつかサンプルが用意されているのでそれを試してみる。

Sprig Cookbook
https://putyourlightson.com/sp...

表示用のテンプレート

{{ sprig('_components/search') }}

{{ sprig.script }}

コンポーネントのテンプレート

{# Sets a default value if not defined by the `query` input field below #}
{% set query = query ?? '' %}

{# Replaces only the `#results` div on keyup or when the value is changed #}
<input sprig s-trigger="keyup changed" s-replace="#results"
  type="text" name="query" value="{{ query }}" placeholder="Search">

<div id="results">
  {% if query %}
    {% set entries = craft.entries.search(query).all() %}
    {% if entries|length %}
    <ul>
      {% for entry in entries %}
        <li><a href="{{ entry.url }}">{{ entry.title }}</a></li>
      {% endfor %}
    </ul>
    {% else %}
        No results
    {% endif %}
  {% endif %}
</div>

表示結果

絞り込みとかそういうのも用意しておくと色々使い勝手は良さそう。

検索系は FlexibleSearch.js とかみたいにあらかじめJSONを出しておいて、それを JS で検索する方が楽だったりはするが。。。

まぁ、Twig だけで諸々完結出来るのであれば、、、というメリットはあるのかもしれない。

Read More

追加で読み込んでいく処理を Twig のコンポーネント側で実行する。

これももちろんJSで追加読み込みしたり、非表示にさせておいたものをJSで表示に切り替えるとか、やり方は色々ある。

表示側のテンプレート

{{ sprig('_components/load-more', {'limit': 2}) }}

{{ sprig.script }}

コンポーネントのテンプレート

{% set offset = offset ?? 0 %}

{% set entries = craft.entries.offset(offset).limit(limit).all() %}

{% for entry in entries %}
  <h6>{{ entry.title }}</h6>
{% endfor %}

{% if entries %}
  {# Increments `offset` by the value of `limit` and swaps itself out on click #}
  <button sprig s-val:offset="{{ offset + limit }}" 
    s-target="this" s-swap="outerHTML">
    Load another
  </button>
{% endif %}

offset の値がクリックのたびに増えていき 2件ずつ追加で読み込まれる。

ユーザーの input を使うときなどは気をつける必要があるけど、 Twig だけでサクッとできるのは楽かもしれない。

他のレシピを見てみると色々出来る。エントリ作成ページとかも作れる。
まぁ、これ自体はデフォルトでも問題ないが。。。

Entry Form | Craft CMS
https://craftcms.com/knowledge...

選択肢が増えたのはありがたいなー