Умные HTML-атрибуты
*******************
.[perex]
Latte 3.1 приносит набор улучшений, посвящённых одному из самых частых занятий в шаблонах - выводу HTML-атрибутов. Он даёт больше удобства, гибкости и безопасности.
Логические атрибуты
===================
В HTML есть особые атрибуты, такие как `checked`, `disabled`, `selected` или `hidden`, у которых конкретное значение не важно: важно лишь их наличие. Они работают как простые флаги.
Latte обрабатывает их автоматически. В атрибут можно передать любое выражение. Если оно истинно, атрибут отрисовывается. Если ложно (например, `false`, `null`, `0` или пустая строка), атрибут полностью опускается.
Это значит, что вы можете распрощаться с громоздкими условиями и `n:attr` и просто написать:
```latte
<input type="text" disabled={$isDisabled} readonly={$isReadOnly}>
```
Если `$isDisabled` равно `false`, а `$isReadOnly` равно `true`, отрисуется:
```latte
<input type="text" readonly>
```
Если вам нужно такое переключение для обычных атрибутов, у которых нет автоматической обработки (например, для атрибутов `data-` или `aria-`), используйте фильтр [toggle |filters#toggle].
Значения null
=============
Это одно из самых приятных изменений. Раньше, если переменная была `null`, она выводилась как пустая строка `""`. Это часто приводило к пустым атрибутам в HTML вроде `class=""` или `title=""`.
В Latte 3.1 действует новое универсальное правило: **значение `null` означает, что атрибута нет.**
```latte
<div title="{$title}"></div>
```
Если `$title` равно `null`, вывод будет `<div></div>`. Если в нём строка, например "Hello", вывод будет `<div title="Hello"></div>`. Благодаря этому вам не нужно оборачивать атрибуты в условия. Это правило действует, когда всё значение атрибута состоит из одного выражения `{...}`; в смешанном значении вроде `title="foo {$bar}"` значение `null` отрисуется как пустая строка.
Если вы используете фильтры, помните, что они обычно преобразуют `null` в строку (например, в пустую). Чтобы этого не происходило, используйте [nullsafe-фильтр |filters#Nullsafe-фильтры] `?|`:
```latte
<div title="{$title?|upper}"></div>
```
Классы
======
В атрибут `class` можно передать массив. Это идеально подходит для условных классов: если массив ассоциативный, ключи используются как имена классов, а значения как условия. Класс отрисуется только тогда, когда условие истинно.
```latte
<button class={[
btn,
btn-primary,
active => $isActive,
]}>Press me</button>
```
Если `$isActive` истинно, отрисуется:
```latte
<button class="btn btn-primary active">Press me</button>
```
Это поведение не ограничивается атрибутом `class`. Оно работает для избранного набора атрибутов, которые ожидают список значений через пробел: `accesskey`, `class`, `headers`, `itemprop`, `ping`, `rel`, `role`, `sandbox` и все атрибуты `aria-*`. Для любого другого атрибута передача массива вызовет предупреждение, а значение будет отброшено.
```latte
<a rel={[nofollow, noopener, external => $isExternal]}>link</a>
```
Стили
=====
Атрибут `style` тоже поддерживает массивы. Особенно это удобно для условных стилей. Если элемент массива содержит ключ (CSS-свойство) и значение, свойство опускается, когда значение равно `null`, `false`, `0` или пустой строке, поэтому, например, `opacity => 0` не отрисуется.
```latte
<div style={[
background => lightblue,
display => $isVisible ? block : null,
font-size => '16px',
]}></div>
```
Если `$isVisible` ложно, отрисуется:
```latte
<div style="background: lightblue; font-size: 16px"></div>
```
Атрибуты data
=============
Часто нам нужно передать в HTML конфигурацию для JavaScript. Раньше это делалось через `json_encode`. Теперь вы можете просто передать в атрибут `data-` массив или объект stdClass, и Latte сериализует его в JSON:
```latte
<div data-config={[ theme: dark, version: 2 ]}></div>
```
Выводит:
```latte
<div data-config='{"theme":"dark","version":2}'></div>
```
Кроме того, `true` и `false` отрисовываются как строки `"true"` и `"false"` (то есть как корректный JSON).
Атрибуты aria
=============
Спецификация WAI-ARIA требует для логических значений текстовые значения `"true"` и `"false"`. Latte делает это для атрибутов `aria-` автоматически:
```latte
<button aria-expanded={=true} aria-checked={=false}></button>
```
Выводит:
```latte
<button aria-expanded="true" aria-checked="false"></button>
```
Точно так же, как `class`, атрибуты `aria-` принимают и массив. Он трактуется как список через пробел: обычные значения используются как есть, а ключ попадает в вывод только тогда, когда его значение равно `true`:
```latte
<span aria-labelledby={[title, description => $hasDescription]}></span>
```
Проверка типов
==============
Вы когда-нибудь видели в сгенерированном HTML `<input value="Array">`? Это классическая ошибка, которая часто остаётся незамеченной. Latte вводит строгую проверку типов для HTML-атрибутов, чтобы ваши шаблоны лучше сопротивлялись подобным недосмотрам.
Latte знает, какой атрибут к какому виду относится и какие значения он ожидает:
- **Обычные атрибуты** (такие как `href`, `id`, `value`, `placeholder`...) ожидают значение, которое можно отрисовать как текст. Сюда относятся строки, числа или объекты, приводимые к строке. Принимается и `null` (он опускает атрибут). Но если вы по ошибке передадите массив, логическое значение или произвольный объект, Latte выдаст предупреждение и разумно проигнорирует некорректное значение.
- **Логические атрибуты** (такие как `checked`, `disabled`...) принимают любой тип, потому что их наличие определяется истинностью значения.
- **Умные атрибуты** (такие как `class`, `style`, `data-`...) специально обрабатывают массивы как корректный ввод.
Эта проверка гарантирует, что ваше приложение не выдаст неожиданный HTML.
Миграция с Latte 3.0
====================
Поскольку поведение `null` (раньше выводилось `""`, теперь атрибут опускается) и атрибутов `data-` (логические значения раньше выводились как `"1"`/`""`, теперь как `"true"`/`"false"`) изменилось, вам может понадобиться обновить шаблоны.
Для плавного перехода Latte предлагает режим миграции, который подсвечивает различия. Прочитайте подробное руководство [Миграция с Latte 3.0 на 3.1|cookbook/migration-from-latte-30].
[* html-attributes.webp *]
Умные HTML-атрибуты
Latte 3.1 приносит набор улучшений, посвящённых одному из самых
частых занятий в шаблонах – выводу HTML-атрибутов. Он даёт больше
удобства, гибкости и безопасности.
Логические атрибуты
В HTML есть особые атрибуты, такие как checked, disabled,
selected или hidden, у которых конкретное значение не важно:
важно лишь их наличие. Они работают как простые флаги.
Latte обрабатывает их автоматически. В атрибут можно передать любое
выражение. Если оно истинно, атрибут отрисовывается. Если ложно
(например, false, null, 0 или пустая строка), атрибут
полностью опускается.
Это значит, что вы можете распрощаться с громоздкими условиями и
n:attr и просто написать:
Если $isDisabled равно false, а $isReadOnly равно true,
отрисуется:
<input type="text" readonly>
Если вам нужно такое переключение для обычных атрибутов, у которых
нет автоматической обработки (например, для атрибутов data- или
aria-), используйте фильтр toggle.
Значения null
Это одно из самых приятных изменений. Раньше, если переменная была
null, она выводилась как пустая строка "". Это часто
приводило к пустым атрибутам в HTML вроде class="" или title="".
В Latte 3.1 действует новое универсальное правило: значение null
означает, что атрибута нет.
<div title="{$title}"></div>
Если $title равно null, вывод будет <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,
]}>Press me</button>
Это поведение не ограничивается атрибутом class. Оно работает
для избранного набора атрибутов, которые ожидают список значений
через пробел: accesskey, class, headers, itemprop,
ping, rel, role, sandbox и все атрибуты aria-*.
Для любого другого атрибута передача массива вызовет предупреждение,
а значение будет отброшено.
Атрибут style тоже поддерживает массивы. Особенно это удобно для
условных стилей. Если элемент массива содержит ключ (CSS-свойство) и
значение, свойство опускается, когда значение равно null,
false, 0 или пустой строке, поэтому, например,
opacity => 0 не отрисуется.
<div style="background: lightblue; font-size: 16px"></div>
Атрибуты data
Часто нам нужно передать в HTML конфигурацию для JavaScript. Раньше это
делалось через json_encode. Теперь вы можете просто передать в
атрибут data- массив или объект stdClass, и Latte сериализует его в JSON:
Точно так же, как class, атрибуты aria- принимают и массив. Он
трактуется как список через пробел: обычные значения используются как
есть, а ключ попадает в вывод только тогда, когда его значение равно
true:
Вы когда-нибудь видели в сгенерированном HTML <input value="Array">?
Это классическая ошибка, которая часто остаётся незамеченной. Latte
вводит строгую проверку типов для HTML-атрибутов, чтобы ваши шаблоны
лучше сопротивлялись подобным недосмотрам.
Latte знает, какой атрибут к какому виду относится и какие значения он
ожидает:
Обычные атрибуты (такие как href, id, value,
placeholder…) ожидают значение, которое можно отрисовать как текст.
Сюда относятся строки, числа или объекты, приводимые к строке.
Принимается и null (он опускает атрибут). Но если вы по ошибке
передадите массив, логическое значение или произвольный объект, Latte
выдаст предупреждение и разумно проигнорирует некорректное
значение.
Логические атрибуты (такие как checked, disabled…)
принимают любой тип, потому что их наличие определяется истинностью
значения.
Умные атрибуты (такие как class, style, data-…)
специально обрабатывают массивы как корректный ввод.
Эта проверка гарантирует, что ваше приложение не выдаст
неожиданный HTML.
Миграция с Latte 3.0
Поскольку поведение null (раньше выводилось "", теперь
атрибут опускается) и атрибутов data- (логические значения раньше
выводились как "1"/"", теперь как "true"/"false")
изменилось, вам может понадобиться обновить шаблоны.
Для плавного перехода Latte предлагает режим миграции, который
подсвечивает различия. Прочитайте подробное руководство Миграция с Latte 3.0 на 3.1.