Хак с Form API в Drupal 7: создаём HTML5‑поля (number, email, tel) без лишних модулей

Drupal 7 предлагает мощный Form API для построения форм. Однако при работе с HTML5‑атрибутами можно столкнуться с неожиданным ограничением: если вы попытаетесь задать тип поля numberemail или tel стандартным способом, Drupal проигнорирует ваше значение и оставит тип text (или тот, который определён через #type).

Рассмотрим ситуацию: нам нужно поле для ввода числа с шагом 10 и ограничениями от 0 до 100. Логично использовать HTML5‑тип number:

Но на выходе мы получим <input type="text" ...>. Почему? Потому что Drupal при рендеринге элемента проставляет тип, основываясь на #type (в данном случае textfield), и атрибут type из #attributes перезаписывается внутренним значением.

Опытные разработчики Drupal 7 знают небольшой хак: если добавить пробел в начало ключа атрибута, Drupal не сможет его сопоставить со своим внутренним списком и просто склеит все атрибуты в итоговом теге. В результате в HTML появятся два атрибута type.

После рендеринга получится примерно такой HTML:

Когда мы добавляем в #attributes элемент с ключом ' type' (с пробелом), Drupal воспринимает его как обычный атрибут, но из-за пробела в имени ключа внутренний механизм Form API не распознаёт его как атрибут type, подлежащий перезаписи. Однако при финальном рендеринге функция drupal_attributes() обрабатывает массив атрибутов и обрезает пробелы в именах ключей. В результате в итоговой разметке атрибут появляется уже без пробела, как обычный type="number".

Как это работает?

Можно заметить интересную деталь: в реальном HTML-коде, который генерирует Drupal, наш атрибут type="number" появляется до стандартного type="text", а не после, как можно было бы ожидать. При этом поле всё равно работает как числовое. Давайте разберёмся почему так происходит, и почему хак не перестаёт работать из-за повторяющихся атрибутов.

Формально это невалидный HTML — атрибут не должен повторяться. Однако браузеры при разборе HTML достаточно либеральны и, как правило, применяют первое встретившееся значение атрибута, игнорируя последующие. В нашем случае браузер видит сначала type="number" и создаёт числовое поле, а второй type="text" просто не оказывает влияния. Именно поэтому хак работает, даже если стандартный type идёт после.

Конечно, поведение браузеров в такой ситуации чётко не специфицировано, и разные версии или браузеры могут теоретически обрабатывать это иначе. Но многолетняя практика использования этого приёма в Drupal 7 показывает, что во всех современных браузерах (Chrome, Firefox, Safari, Edge) поле становится именно того типа, который указан первым.

Мало букафф? Читайте есчо !

Получение списка SQL-запросов через Devel: отладка в нестандартных сценариях

Июль 22, 2026 г.

В процессе разработки на Drupal иногда возникает необходимость проанализировать, какие SQL-запросы выполняются при обработке того или иного запроса. Стандартный интерфейс Devel (например, панель внизу страницы) отлично справляется с этой задачей для обычных ...

Читать

Список всех типов публикаций в Drupal

Май 13, 2020 г.

Как получить полный список зарегистрированных типов публикаций в Drupal 7. Задача типична для бек-енда при создании форм страниц настроек. Потому покажу в статье пример реализации поля для формы с выбором типов публикаций. В API Drupal существует ...

Читать

Как рендерить отдельные поля элемента field collections

Январь 31, 2019 г.

Модуль field_collection всю свою историю существования (аж 2010 года) проходит в статусе beta версии. Тем не менее многие разработчики используют его в своих проектах. На текущий момент это версия 7.x-1.0-beta13. Хотя FC - это ещё один entity, ...

Читать

Изменения настроек поля программно Drupal 7

Май 27, 2020 г.

Если вам программно нужно изменить настройки поля в Drupal, то на помощь приходит Field CRUD API. Это набор функций из файла modules/field/field.crud.inc. ...

Читать
 

Комментарии к «Хак с Form API в Drupal 7: создаём HTML5‑поля (number, email, tel) без лишних модулей»

Понравилась статья? Есть вопросы? - пишите в комментариях.



Комментарий: