2022年3月23日に『Drupal テーマ開発入門講座 第2回 シンプルなカスタムテーマを作ってみよう』に参加して、テスト環境でサブテーマを作ったので、その環境を使って、かつてからしばしば問題になるcomposite elementの表示順序の変更に挑戦した。
一番典型的なのは、名前で英語の世界だと並びはFirst name, Last nameの順だが、日本語では姓、名の順である。Webformで名前フィールドを定義すると以下のような表示になってしまう。
これを以下のようにしたい。
冒頭の画像は、webform-composite-name.html.twigが名前フィールドの表示に使われていて、それをサブテーマ(web/themes/custom/marucha)のtemplateで代替していることを示しているものだ。これは、昨日のWebinarでservices.ymlでdebug: trueにしたので、どのtwigが用いられているのか追跡可能になったことで手が出せるようになったのである。
まずは、webformモジュールの下のtemplateディレクトリからwebform-composite-name.html.twigをサブテーマのtemplateにコピーする。元となるファイルは以下の通り。
{#
/**
* @file
* Default theme implementation of a name composite webform element.
*
* Available variables:
* - content: The name webform element to be output.
* - flexbox: Determines if Flexbox layout should be applied to the composite
* element.
*
* @see template_preprocess_webform_composite_name()
*
* @ingroup themeable
*/
#}
{% if flexbox %}
<div class="webform-name">
<div class="webform-flexbox">
{% if content.title %}
<div class="webform-flex webform-flex--2 webform-name__title"><div class="webform-flex--container">{{ content.title }}</div></div>
{% endif %}
{% if content.first %}
<div class="webform-flex webform-flex--3 webform-name__first"><div class="webform-flex--container">{{ content.first }}</div></div>
{% endif %}
{% if content.middle %}
<div class="webform-flex webform-flex--2 webform-name__middle"><div class="webform-flex--container">{{ content.middle }}</div></div
>
{% endif %}
{% if content.last %}
<div class="webform-flex webform-flex--3 webform-name__last"><div class="webform-flex--container">{{ content.last }}</div></div>
{% endif %}
{% if content.suffix %}
<div class="webform-flex webform-flex--1 webform-name__suffix"><div class="webform-flex--container">{{ content.suffix }}</div></div
>
{% endif %}
{% if content.degree %}
<div class="webform-flex webform-flex--1 webform-name__degree"><div class="webform-flex--container">{{ content.degree }}</div></div
>
{% endif %}
</div>
</div>
{% else %}
{{ content }}
{% endif %}
flexboxがオンになっているときには、それぞれにクラスを割り付ける処理が書かれている。この順序が表示順になっているので、これを変えてやれば良い。
{#
/**
* @file
* Default theme implementation of a name composite webform element.
*
* Available variables:
* - content: The name webform element to be output.
* - flexbox: Determines if Flexbox layout should be applied to the composite
* element.
*
* @see template_preprocess_webform_composite_name()
*
* @ingroup themeable
*/
#}
{% if flexbox %}
<div class="webform-name">
<div class="webform-flexbox">
{% if content.last %}
<div class="webform-flex webform-flex--3 webform-name__last"><div class="webform-flex--container">{{ content.last }}</div></div>
{% endif %}
{% if content.first %}
<div class="webform-flex webform-flex--3 webform-name__first"><div class="webform-flex--container">{{ content.first }}</div></div>
{% endif %}
{% if content.middle %}
<div class="webform-flex webform-flex--2 webform-name__middle"><div class="webform-flex--container">{{ content.middle }}</div></div
>
{% endif %}
{% if content.suffix %}
<div class="webform-flex webform-flex--1 webform-name__suffix"><div class="webform-flex--container">{{ content.suffix }}</div></div
>
{% endif %}
{% if content.degree %}
<div class="webform-flex webform-flex--1 webform-name__degree"><div class="webform-flex--container">{{ content.degree }}</div></div
>
{% endif %}
{% if content.title %}
<div class="webform-flex webform-flex--2 webform-name__title"><div class="webform-flex--container">{{ content.title }}</div></div>
{% endif %}
</div>
</div>
{% else %}
{{ content.last }}
{{ content.first }}
{{ content.middle }}
{{ content.suffix }}
{{ content.degres }}
{{ content.title }}
{% endif %}
flexboxがオンの場合はlastを最初に持ってきて、titleを最後に移し、elseについては明示的に一段下の要素を列挙する形にした。バグが出るかもしれないが、今の所問題なく動いている。
後は、Submission displayは個別のtemplateがなく{{ content }}が適用されてしまうので、これはwebformの定義画面で表示順を明示する。
コントリビューションモジュールに手を加えること無く済ませられるのは大変ありがたい。
なお、本当はlocaleで英語版の順序と喧嘩することのないtwigを作れればよいのだろうが、残念ながらlanguageをうまく取得できなかった。そこまでできたら、webformへの仕様提案も考えたほうが良いと思っている。
いずれにしても、Drupalがデータ構造と表示をかなり丁寧に分離していることの強みが感じられて満足。