Рендеринг форм
Зовнішній вигляд форм може бути дуже різноманітним. На практиці ми
можемо зіткнутися з двома крайнощами. З одного боку, є потреба
відрендерити серію форм у додатку, які візуально схожі одна на одну, і
ми цінуємо простий рендеринг без шаблону за допомогою
$form->render()
. Зазвичай це стосується адміністративних
інтерфейсів.
З іншого боку, існують різні форми, де кожна з них унікальна. Їх зовнішній вигляд найкраще описати за допомогою мови HTML в шаблоні. І, звичайно, крім обох згаданих крайнощів, ми зустрінемо багато форм, які знаходяться десь посередині.
Візуалізація за допомогою Latte
Система шаблонів Latte докорінно полегшує відтворення форм та їхніх елементів. Спочатку ми покажемо, як відтворювати форми вручну, елемент за елементом, щоб отримати повний контроль над кодом. Пізніше ми покажемо, як автоматизувати такий рендеринг.
Ви можете отримати пропозицію шаблону Latte для форми,
згенерованої за допомогою методу Nette\Forms\Blueprint::latte($form)
, який
виведе її на сторінку браузера. Потім вам просто потрібно вибрати код
одним клацанням миші і скопіювати його в свій проект.
{control}
Найпростіший спосіб відобразити форму – написати її в шаблоні:
Зовнішній вигляд відмальованої форми можна змінити, налаштувавши Renderer і окремі елементи керування.
n:name
Дуже легко пов'язати визначення форми в PHP-коді з HTML-кодом. Просто
додайте атрибути n:name
. Ось як це просто!
Зовнішній вигляд отриманого HTML-коду повністю у ваших руках. Якщо ви
використовуєте атрибут n:name
з <select>
, <button>
або
<textarea>
елементами, їхній внутрішній вміст заповнюється
автоматично. Крім того, тег <form n:name>
тег створює локальну
змінну $form
з намальованим об'єктом форми, а закриваючий тег
</form>
перемальовує всі недомальовані приховані елементи (те
саме стосується і {form} ... {/form}
).
Однак не варто забувати про виведення можливих повідомлень про
помилки. Як тих, які були додані до окремих елементів методом
addError()
(за допомогою {inputError}
), так і тих, які були додані
безпосередньо до форми (повертаються методом $form->getOwnErrors()
):
Більш складні елементи форми, такі як RadioList або CheckboxList, можуть бути відображені елемент за елементом:
{label}
{input}
Чи не хочете ви подумати для кожного елемента, який HTML-елемент
використовувати для нього в шаблоні? <input>
, <textarea>
і
т.д.? Рішенням є універсальний тег {input}
:
Якщо форма використовує перекладач, то текст усередині тегів
{label}
буде перекладено.
Знову ж таки, складніші елементи форми, такі як RadioList або CheckboxList, можуть виводитися поелементно:
Щоб відобразити <input>
в елементі Checkbox, використовуйте
{input myCheckbox:}
. Атрибути HTML повинні бути розділені комою
{input myCheckbox:, class: required}
.
{inputError}
Виводить повідомлення про помилку для елемента форми, якщо воно є.
Повідомлення зазвичай обертається в HTML-елемент для стилізації.
Уникнути виведення порожнього елемента за відсутності повідомлення
можна за допомогою n:ifcontent
:
Ми можемо визначити наявність помилки за допомогою методу
hasErrors()
і встановити клас батьківського елемента
відповідним чином:
{form}
Мітки {form signInForm}...{/form}
є альтернативою
<form n:name="signInForm">...</form>
.
Автоматичний рендеринг
За допомогою тегів {input}
і {label}
ми можемо легко створити
загальний шаблон для будь-якої форми. Він буде ітерувати і послідовно
виводити всі елементи форми, за винятком прихованих елементів, які
виводяться автоматично під час завершення форми за допомогою тега
</form>
тега. Він буде очікувати ім'я намальованої форми у
змінній $form
.
Використовувані парні самозакривні теги {label .../}
відображають
мітки, що надходять із визначення форми в PHP-коді.
Ви можете зберегти цей загальний шаблон у файлі basic-form.latte
і для
візуалізації форми просто увімкнути його та передати ім'я форми (або
екземпляр) у параметр $form
:
Якщо ви хочете вплинути на зовнішній вигляд однієї конкретної форми і намалювати один елемент по-іншому, то найпростіший спосіб – це підготувати в шаблоні блоки, які можна перезаписати пізніше. Блоки також можуть мати динамічні імена, тому ви можете вставити в них ім'я елемента, який потрібно намалювати. Наприклад:
Для елемента, наприклад, username
створюється блок input-username
,
який можна легко перевизначити за допомогою тега {embed}:
Альтернативно, весь вміст шаблону basic-form.latte
може бути визначено як блок, включаючи
параметр $form
:
Це дещо спростить його використання:
Вам потрібно буде імпортувати блок тільки в одному місці, на початку шаблону макета:
Особливі випадки
Якщо вам потрібно відобразити тільки внутрішню частину форми без
HTML-тегів <form>
наприклад, при надсиланні фрагментів,
приховайте їх за допомогою атрибута n:tag-if
:
Тег formContainer
допомагає при відтворенні даних, що вводяться,
всередині контейнера форми.
Рендеринг без латте
Найпростіший спосіб відобразити форму – викликати:
Зовнішній вигляд відмальованої форми можна змінити, налаштувавши Renderer і окремі елементи керування.
Рендеринг вручну
Кожен елемент форми має методи, які генерують HTML код для поля і мітки форми. Вони можуть повертати його у вигляді рядка або об'єкта Nette\Utils\Html:
getControl(): Html|string
повертає HTML-код елементаgetLabel($caption = null): Html|string|null
повертає HTML-код мітки, якщо така є
Це дає змогу відображати форму елемент за елементом:
Тоді як для деяких елементів getControl()
повертає один HTML-елемент
(наприклад. <input>
, <select>
тощо), для інших він повертає
цілий шматок HTML-коду (CheckboxList, RadioList). У цьому випадку можна
використовувати методи, що генерують окремі входи і мітки, для кожного
елемента окремо:
getControlPart($key = null): ?Html
повертає HTML-код одного елемента.getLabelPart($key = null): ?Html
повертає HTML-код для мітки окремого елемента
Ці методи мають префікс get
з історичних причин, але
generate
було б краще, тому що він створює і повертає новий елемент
Html
при кожному виклику.
Рендерер
Це об'єкт, що забезпечує рендеринг форми. Він може бути встановлений
методом $form->setRenderer
. Йому передається керування при виклику
методу $form->render()
.
Якщо ми не задамо користувацький рендерер, буде використовуватися рендерер за замовчуванням Nette\Forms\Rendering\DefaultFormRenderer. У результаті елементи форми будуть відображені у вигляді HTML-таблиці. Виведення має такий вигляд:
Використовувати таблицю чи ні – вирішувати вам, багато
веб-дизайнерів віддають перевагу іншій розмітці, наприклад, списку. Ми
можемо налаштувати DefaultFormRenderer
так, щоб він взагалі не виводився
в таблицю. Ми просто повинні встановити відповідні $wrappers.
Перший індекс завжди представляє область, а другий – елемент. Усі
відповідні області показано на малюнку:

За замовчуванням група controls
обгорнута в. <table>
і кожен
pair
являє собою рядок таблиці <tr>
що містить пару
label
і control
(комірки <th>
и <td>
). Давайте
змінимо всі ці елементи обгортки. Ми загорнемо controls
у
<dl>
, залишимо pair
на самоті, помістимо label
у
<dt>
і обернемо control
в <dd>
:
У результаті вийде наступний фрагмент:
Обгортки можуть впливати на багато атрибутів. Наприклад:
- додати спеціальні класи CSS до кожного введення форми
- розрізняти парні та непарні рядки
- по-різному малювати обов'язкові та необов'язкові елементи
- встановити, чи будуть повідомлення про помилки показуватися над формою або поруч із кожним елементом
Опції
Поведінкою Renderer також можна керувати, встановлюючи опції для окремих елементів форми. Таким чином, ви можете встановити спливаючу підказку, яка відображатиметься поруч із полем введення:
Якщо ми хочемо помістити в нього HTML-контент, ми використовуємо клас Html.
Html-елемент також можна використовувати замість label:
$form->addCheckbox('conditions', $label)
.
Групування входів
Поля введення можна об'єднати в набори візуальних полів, створивши групу:
Створення нової групи активує її – усі додані далі елементи додаються в цю групу. Ви можете побудувати форму таким чином:
Рендер спочатку малює групи, а потім елементи, які не належать до жодної групи.
Підтримка Bootstrap
Ви можете знайти приклади налаштування рендерера для Twitter Bootstrap 2, Bootstrap 3 і Bootstrap 4
Атрибути HTML
Щоб задати довільні HTML-атрибути для елементів форми, скористайтеся
методом setHtmlAttribute(string $name, $value = true)
:
Вказівка типу елемента:
Встановлення типу та інших атрибутів слугує лише для візуальних цілей. Перевірка коректності введення повинна відбуватися на сервері, що ви можете забезпечити, вибравши відповідний елемент управління формою і вказавши правила перевірки.
Для окремих елементів у перемикачах або списках ми можемо встановити
HTML-атрибут з різними значеннями для кожного з них. Зверніть увагу на
двокрапку після style:
, яка забезпечує вибір значення на
основі ключа:
Відображається як:
Для задання булевих атрибутів, таких як readonly
, ми можемо
використовувати позначення зі знаком питання:
Відображається як:
Для селекбоксів метод setHtmlAttribute()
встановлює атрибути елемента
<select>
. Якщо ми хочемо встановити атрибути для кожного
<option>
, ми будемо використовувати метод setOptionAttribute()
.
Крім того, двокрапка і знак питання, використані вище, працюють:
Відображається як:
Прототипи
Альтернативним способом встановлення атрибутів HTML є зміна шаблону,
на основі якого генерується елемент HTML. Шаблон є об'єктом Html
і
повертається методом getControlPrototype()
:
Шаблон мітки, що повертається методом getLabelPrototype()
, також може
бути змінений таким чином:
Для елементів Checkbox, CheckboxList і RadioList ви можете вплинути на шаблон
елемента, який обертає елемент. Його повертає getContainerPrototype()
. За
замовчуванням це „порожній“ елемент, тому нічого не відображається,
але якщо дати йому ім'я, він буде відображатися:
У випадку CheckboxList і RadioList можна також вплинути на шаблон роздільника
елементів, що повертається методом getSeparatorPrototype()
. За
замовчуванням це елемент <br>
. Якщо ви зміните його на парний
елемент, він буде обволікати окремі елементи замість того, щоб
розділяти їх. Також можна впливати на шаблон HTML-елемента міток
елементів, який повертає метод getItemLabelPrototype()
.
Переклад
Якщо ви програмуєте багатомовний додаток, вам, ймовірно, знадобиться рендерити форму різними мовами. Для цього в Nette Framework передбачено інтерфейс перекладу Nette\Localization\Translator. У Nette немає реалізації за замовчуванням, ви можете вибрати відповідно до ваших потреб з декількох готових рішень, які ви можете знайти на Componette. Їх документація підкаже вам, як налаштувати перекладач.
Форма підтримує виведення тексту через перекладач. Ми передаємо його
за допомогою методу setTranslator()
:
Відтепер не тільки всі підписи, але й усі повідомлення про помилки або значення у вибраних полях будуть перекладені на іншу мову.
Ви можете встановити інший перекладач для окремих елементів форми
або повністю вимкнути переклад за допомогою null
:
Для правил валідації перекладачеві також передаються певні параметри, наприклад, для правила:
викликається транслятор з наступними параметрами:
і таким чином може вибрати правильну форму множини для слова
characters
за підрахунком.
Подія onRender
Безпосередньо перед відображенням форми ми можемо викликати наш код. Це може, наприклад, додати HTML-класи до елементів форми для правильного відображення. Додамо код у масив ‚onRender‘: