スマートな HTML 属性

Latte 3.1 では、テンプレートで最もよく行われる作業のひとつである HTML 属性の出力に的を絞った一連の改善が入りました。快適さ、柔軟さ、そして安全性が高まります。

真偽値属性

HTML には checkeddisabledselectedhidden のような特別な属性があり、具体的な値は意味を持たず、存在するかどうかだけが問われます。単純なフラグとして働くわけです。

Latte はこれらを自動的に扱います。属性には任意の式を渡せます。真であれば属性が出力され、偽(falsenull0、空文字列など)であれば属性はまるごと省かれます。

つまり、面倒な条件分岐や n:attr とはお別れして、単にこう書けます。

<input type="text" disabled={$isDisabled} readonly={$isReadOnly}>

$isDisabledfalse$isReadOnlytrue なら、次のように出力されます。

<input type="text" readonly>

この自動処理を持たない標準の属性(data-aria- 属性など)で同じ切り替えをしたい場合は、toggle フィルタを使ってください。

null 値

これは最も嬉しい変更のひとつです。以前は変数が null のとき、空文字列 "" として出力されていました。そのため HTML に class=""title="" のような空の属性が現れがちでした。

Latte 3.1 では新しい統一ルールが適用されます。値が null なら、その属性は存在しない。

<div title="{$title}"></div>

$titlenull なら出力は <div></div> です。文字列(たとえば “Hello”)が入っていれば <div title="Hello"></div> になります。おかげで属性を条件で包む必要がありません。このルールは属性値が丸ごとひとつの {...} 式である場合に適用されます。title="foo {$bar}" のような混在した値では、null は空文字列として出力されます。

フィルタを使う場合は、たいてい null が文字列(たとえば空文字列)に変換されることに注意してください。それを避けるには nullsafe フィルタ ?| を使います。

<div title="{$title?|upper}"></div>

クラス

class 属性には配列を渡せます。これは条件付きクラスにぴったりです。連想配列であれば、キーがクラス名、値が条件として使われます。条件が真のときだけそのクラスが出力されます。

<button class={[
	btn,
	btn-primary,
	active => $isActive,
]}>押してください</button>

$isActive が真なら、次のように出力されます。

<button class="btn btn-primary active">押してください</button>

この振る舞いは class に限りません。空白区切りの値のリストを期待する一連の属性、すなわち accesskeyclassheadersitemproppingrelrolesandbox、そしてすべての aria-* 属性で機能します。それ以外の属性に配列を渡すと警告が出て、値は捨てられます。

<a rel={[nofollow, noopener, external => $isExternal]}>リンク</a>

スタイル

style 属性も配列に対応しています。条件付きのスタイルに特に便利です。配列の項目がキー(CSS プロパティ)と値を持つ場合、値が nullfalse0、空文字列のときはそのプロパティが省かれます。たとえば opacity => 0 は出力されません。

<div style={[
	background => lightblue,
	display => $isVisible ? block : null,
	font-size => '16px',
]}></div>

$isVisible が偽なら、次のように出力されます。

<div style="background: lightblue; font-size: 16px"></div>

data 属性

JavaScript 向けの設定を HTML に渡したいことはよくあります。以前は json_encode を使っていました。今は配列や stdClass オブジェクトを data- 属性に渡すだけで、Latte が JSON にシリアライズしてくれます。

<div data-config={[ theme: dark, version: 2 ]}></div>

出力:

<div data-config='{"theme":"dark","version":2}'></div>

さらに truefalse は文字列 "true""false" として出力されます(つまり正しい JSON です)。

aria 属性

WAI-ARIA 仕様は真偽値に対してテキスト値 "true""false" を要求します。Latte は aria- 属性についてこれを自動的に扱います。

<button aria-expanded={=true} aria-checked={=false}></button>

出力:

<button aria-expanded="true" aria-checked="false"></button>

class と同じく、aria- 属性も配列を受け取ります。空白区切りのリストとして扱われ、素の値はそのまま使われ、キーはその値が true のときだけ含まれます。

<span aria-labelledby={[title, description => $hasDescription]}></span>

型チェック

生成された HTML の中に <input value="Array"> を見つけたことはありませんか。見過ごされがちな典型的なバグです。Latte は HTML 属性に対して厳格な型チェックを導入し、テンプレートがこうした見落としに強くなるようにしました。

Latte はどの属性がどういう種類で、どんな値を期待するかを知っています。

  • 標準の属性hrefidvalueplaceholder など)は、テキストとして出力できる値を期待します。文字列、数値、文字列化できるオブジェクトが該当します。null も受け付けます(属性が消えます)。ただし、うっかり配列や真偽値、一般的なオブジェクトを渡すと、Latte は警告を出し、その不正な値を賢く無視します。
  • 真偽値属性checkeddisabled など)は、存在の有無が真偽で決まるため、どんな型でも受け付けます。
  • スマート属性classstyledata- など)は、配列を正しい入力として特別に扱います。

このチェックにより、アプリケーションが思いがけない HTML を出力しなくなります。

Latte 3.0 からの移行

null の振る舞い(以前は "" を出力、現在は属性を削除)と data- 属性(以前は真偽値が "1"/""、現在は "true"/"false")が変わったため、テンプレートの更新が必要になることがあります。

スムーズに移行できるよう、Latte には違いを示す移行モードが用意されています。詳しくは Latte 3.0 から 3.1 への移行をご覧ください。

バージョン: 3.x