Элементы форм
Обзор стандартных элементов форм.
addText (string $name, $label=null, ?int $cols=null, ?int $maxLength=null): TextInput
Добавляет однострочное текстовое поле (класс TextInput). Если пользователь
поле не заполнит, оно вернёт пустую строку '', либо через
setNullable() можно добиться, чтобы вместо неё возвращался
null.
$form->addText('name', 'Имя:')
->setRequired()
->setNullable();
Автоматически проверяет UTF-8, обрезает пробелы слева и справа и удаляет переводы строк, которые мог отправить злоумышленник.
Максимальную длину можно ограничить методом setMaxLength(). Метод addFilter() позволяет
изменить значение, введённое пользователем.
С помощью setHtmlType() можно сменить внешний вид текстового поля на
типы вроде search, tel или url, определённые в спецификации. Помните, что
смена типа – чисто визуальная и не заменяет функцию проверки. Для типа
url уместно добавить конкретное правило проверки URL.
Для других типов полей, таких как number, range,
email, date, datetime-local, time и color,
используйте специализированные методы addInteger(), addFloat(), addEmail(), addDate(), addTime(), addDateTime() и addColor(),
которые обеспечивают проверку на стороне сервера. Типы month и
week пока поддерживаются не всеми браузерами полностью.
Элементу можно задать “пустое значение”. Оно ведёт себя примерно
как значение по умолчанию, но если пользователь его не изменит, элемент
вернёт пустую строку или null.
$form->addText('phone', 'Телефон:')
->setHtmlType('tel')
->setEmptyValue('+420');
addTextArea (string $name, $label=null): TextArea
Добавляет многострочное текстовое поле (класс TextArea). Если пользователь
поле не заполнит, оно вернёт пустую строку '', либо через
setNullable() можно добиться, чтобы вместо неё возвращался
null.
$form->addTextArea('note', 'Заметка:')
->addRule($form::MaxLength, 'Ваша заметка слишком длинная', 10000);
Автоматически проверяет UTF-8 и приводит окончания строк к \n. В
отличие от однострочного поля, обрезки пробелов не происходит.
Максимальную длину можно ограничить методом setMaxLength(). Метод addFilter() позволяет
изменить введённое пользователем значение. Пустое значение задаётся
через setEmptyValue().
addInteger (string $name, $label=null): TextInput
Добавляет поле для ввода целого числа (класс TextInput). Возвращает либо
целое число, либо null, если пользователь ничего не введёт.
$form->addInteger('year', 'Год:')
->addRule($form::Range, 'Год должен быть между %d и %d.', [1900, 2023]);
Элемент отрисовывается как <input type="number">. Методом
setHtmlType() можно сменить тип на range для отображения
ползунком либо на text, если вы предпочитаете обычное текстовое
поле без особого поведения типа number.
addFloat (string $name, $label=null): TextInput
Добавляет поле для ввода дробного числа (класс TextInput). Возвращает либо
число с плавающей точкой, либо null, если пользователь ничего не
введёт.
$form->addFloat('level', 'Уровень:')
->setDefaultValue(0)
->addRule($form::Range, 'Уровень должен быть между %d и %d.', [0, 100]);
Элемент отрисовывается как <input type="number">. Методом
setHtmlType() можно сменить тип на range для отображения
ползунком либо на text, если вы предпочитаете обычное текстовое
поле без особого поведения типа number.
Nette и браузер Chrome принимают в качестве десятичного разделителя и
запятую, и точку. Чтобы эта возможность работала и в Firefox, рекомендуется
задать атрибут lang либо конкретному элементу, либо всей
странице, например <html lang="en">.
addEmail (string $name, $label=null, int $maxLength=255): TextInput
Добавляет поле для ввода адреса электронной почты (класс TextInput). Если пользователь
поле не заполнит, оно вернёт пустую строку '', либо через
setNullable() можно добиться, чтобы вместо неё возвращался
null.
$form->addEmail('email', 'E-mail:');
Проверяет, что значение – корректный адрес электронной почты. Существование домена не проверяется, проверяется только синтаксис. Автоматически проверяет UTF-8 и обрезает пробелы слева и справа.
Максимальную длину можно ограничить методом setMaxLength(). Метод addFilter() позволяет
изменить введённое пользователем значение. Пустое значение задаётся
через setEmptyValue().
addPassword (string $name, $label=null, ?int $cols=null, ?int $maxLength=null): TextInput
Добавляет поле для ввода пароля (класс TextInput).
$form->addPassword('password', 'Пароль:')
->setRequired()
->addRule($form::MinLength, 'Пароль должен быть длиной не менее %d символов', 8)
->addRule($form::Pattern, 'Пароль должен содержать цифру', '.*[0-9].*');
При повторном отображении формы поле будет пустым. Автоматически проверяет UTF-8, обрезает пробелы слева и справа и удаляет переводы строк, которые мог отправить злоумышленник.
addCheckbox (string $name, $caption=null): Checkbox
Добавляет флажок (класс Checkbox). Возвращает true
или false в зависимости от того, отмечен ли он.
$form->addCheckbox('agree', 'Я согласен с условиями')
->setRequired('С условиями нужно согласиться');
addCheckboxList (string $name, $label=null, ?array $items=null): CheckboxList
Добавляет список флажков для выбора нескольких пунктов (класс CheckboxList). Возвращает
массив ключей выбранных пунктов. Метод getSelectedItems() возвращает
выбранные пункты парами ключ-значение.
$form->addCheckboxList('colors', 'Цвета:', [
'r' => 'красный',
'g' => 'зелёный',
'b' => 'синий',
]);
Массив предлагаемых пунктов передайте третьим параметром или
методом setItems(). Если вторым аргументом setItems() передать
false, значения будут использованы и как ключи.
Отдельные пункты отключаются через setDisabled(['r', 'g']).
Элемент автоматически проверяет, что подделки не произошло, что
выбранные пункты действительно были среди предложенных и не были
отключены. Методом getRawValue() можно получить отправленные пункты
без этой важной проверки.
При задании выбранных по умолчанию пунктов тоже проверяется, что они
есть среди предложенных, иначе выбрасывается исключение. Эту проверку
можно отключить через checkDefaultValue(false).
Если вы отправляете форму методом GET, можно выбрать более
компактный способ передачи данных, экономящий размер строки запроса.
Он включается заданием HTML-атрибута формы:
$form->setHtmlAttribute('data-nette-compact');
addRadioList (string $name, $label=null, ?array $items=null): RadioList
Добавляет радиокнопки (класс RadioList). Возвращает ключ
выбранного пункта либо null, если пользователь ничего не выбрал.
Метод getSelectedItem() возвращает не ключ, а значение.
$sex = [
'm' => 'мужской',
'f' => 'женский',
'o' => 'другой',
];
$form->addRadioList('gender', 'Пол:', $sex);
Массив предлагаемых пунктов передайте третьим параметром или
методом setItems().
Отдельные пункты отключаются через setDisabled(['m']).
Элемент автоматически проверяет, что подделки не произошло, что
выбранный пункт действительно был среди предложенных и не был
отключён. Методом getRawValue() можно получить отправленный пункт без
этой важной проверки.
При задании выбранного по умолчанию пункта тоже проверяется, что он
есть среди предложенных, иначе выбрасывается исключение. Эту проверку
можно отключить через checkDefaultValue(false).
addSelect (string $name, $label=null, ?array $items=null, ?int $size=null): SelectBox
Добавляет выпадающий список (класс SelectBox). Возвращает ключ
выбранного пункта либо null, если пользователь ничего не выбрал.
Метод getSelectedItem() возвращает не ключ, а значение.
$countries = [
'CZ' => 'Чехия',
'SK' => 'Словакия',
'GB' => 'Великобритания',
];
$form->addSelect('country', 'Страна:', $countries)
->setDefaultValue('SK');
Массив предлагаемых пунктов передайте третьим параметром или
методом setItems(). Пункты могут быть и двумерным массивом (он
представляет optgroup):
$countries = [
'Европа' => [
'CZ' => 'Чехия',
'SK' => 'Словакия',
'GB' => 'Великобритания',
],
'CA' => 'Канада',
'US' => 'США',
'?' => 'другая',
];
У выпадающих списков первый пункт часто имеет особое значение и
служит призывом к действию. Для добавления такого пункта служит метод
setPrompt().
$form->addSelect('country', 'Страна:', $countries)
->setPrompt('Выберите страну');
Отдельные пункты отключаются через setDisabled(['CZ', 'SK']).
Элемент автоматически проверяет, что подделки не произошло, что
выбранный пункт действительно был среди предложенных и не был
отключён. Методом getRawValue() можно получить отправленный пункт без
этой важной проверки.
При задании выбранного по умолчанию пункта тоже проверяется, что он
есть среди предложенных, иначе выбрасывается исключение. Эту проверку
можно отключить через checkDefaultValue(false).
addMultiSelect (string $name, $label=null, ?array $items=null, ?int $size=null): MultiSelectBox
Добавляет выпадающий список для выбора нескольких пунктов (класс MultiSelectBox). Возвращает
массив ключей выбранных пунктов. Метод getSelectedItems() возвращает
выбранные пункты парами ключ-значение.
$form->addMultiSelect('countries', 'Страны:', $countries);
Массив предлагаемых пунктов передайте третьим параметром или
методом setItems(). Пункты могут быть и двумерным массивом.
Отдельные пункты отключаются через setDisabled(['CZ', 'SK']).
Элемент автоматически проверяет, что подделки не произошло, что
выбранные пункты действительно были среди предложенных и не были
отключены. Методом getRawValue() можно получить отправленные пункты
без этой важной проверки.
При задании выбранных по умолчанию пунктов тоже проверяется, что они
есть среди предложенных, иначе выбрасывается исключение. Эту проверку
можно отключить через checkDefaultValue(false).
addUpload (string $name, $label=null): UploadControl
Добавляет поле для загрузки файла (класс UploadControl). Возвращает
объект FileUpload, даже если
пользователь никакого файла не загрузил, что можно выяснить методом
FileUpload::hasFile(). С помощью setNullable() можно добиться, чтобы при
отсутствии загруженного файла элемент возвращал null вместо
объекта FileUpload.
$form->addUpload('avatar', 'Аватар:')
->addRule($form::Image, 'Аватар должен быть JPEG, PNG, GIF, WebP или AVIF.')
->addRule($form::MaxFileSize, 'Максимальный размер - 1 МБ.', 1024 * 1024);
Если файл не удалось загрузить корректно, форма не считается успешно
отправленной и отображается ошибка. То есть при успешной отправке
проверять метод FileUpload::isOk() не нужно.
Никогда не доверяйте исходному имени файла, которое возвращает метод
FileUpload::getName(): клиент мог отправить вредоносное имя файла с
намерением повредить или взломать ваше приложение.
Правила MimeType и Image определяют нужный тип по сигнатуре
файла и не проверяют его целостность. Выяснить, не повреждено ли
изображение, можно, например, попыткой его загрузить.
addMultiUpload (string $name, $label=null): UploadControl
Добавляет поле для загрузки нескольких файлов сразу (класс UploadControl). Возвращает
массив объектов FileUpload. Метод
FileUpload::hasFile() у каждого из них вернёт true.
$form->addMultiUpload('files', 'Файлы:')
->addRule($form::MaxLength, 'Можно загрузить не более %d файлов.', 10);
Если какой-нибудь файл не удалось загрузить корректно, форма не
считается успешно отправленной и отображается ошибка. То есть при
успешной отправке проверять метод FileUpload::isOk() у каждого файла
не нужно.
Никогда не доверяйте исходным именам файлов, которые возвращает
метод FileUpload::getName(): клиент мог отправить вредоносные имена
файлов с намерением повредить или взломать ваше приложение.
Правила MimeType и Image определяют нужный тип по сигнатуре
файла и не проверяют его целостность. Выяснить, не повреждено ли
изображение, можно, например, попыткой его загрузить.
addDate (string $name, $label=null): DateTimeControl
Добавляет поле, которое позволяет пользователю легко ввести дату из года, месяца и дня (класс DateTimeControl).
В качестве значения по умолчанию оно принимает объекты, реализующие
DateTimeInterface, строку со временем или число, обозначающее временную
метку UNIX. То же относится к аргументам правил Min, Max или
Range, задающих минимальную и максимальную допустимую дату.
$form->addDate('date', 'Дата:')
->setDefaultValue(new DateTime)
->addRule($form::Min, 'Дата должна быть не менее чем месячной давности.', new DateTime('-1 month'));
По умолчанию возвращает объект DateTimeImmutable. Методом
setFormat() можно задать текстовый формат
или временную метку:
$form->addDate('date', 'Дата:')
->setFormat('Y-m-d');
addTime (string $name, $label=null, bool $withSeconds=false): DateTimeControl
Добавляет поле, которое позволяет пользователю легко ввести время из часов, минут и необязательно секунд (класс DateTimeControl).
В качестве значения по умолчанию оно принимает объекты, реализующие
DateTimeInterface, строку со временем или число, обозначающее временную
метку UNIX. Из этих входных данных используются только сведения о
времени, дата игнорируется. То же относится к аргументам правил
Min, Max или Range, задающих минимальное и максимальное
допустимое время. Если заданное минимальное значение больше
максимального, возникает диапазон времени, проходящий через
полночь.
$form->addTime('time', 'Время:', withSeconds: true)
->addRule($form::Range, 'Время должно быть между %d и %d.', ['12:30', '13:30']);
По умолчанию возвращает объект DateTimeImmutable (с датой, заданной
как 1 января 1 года). Методом setFormat() можно задать текстовый
формат:
$form->addTime('time', 'Время:')
->setFormat('H:i');
addDateTime (string $name, $label=null, bool $withSeconds=false): DateTimeControl
Добавляет поле, которое позволяет пользователю легко ввести и дату, и время из года, месяца, дня, часов, минут и необязательно секунд (класс DateTimeControl).
В качестве значения по умолчанию оно принимает объекты, реализующие
DateTimeInterface, строку со временем или число, обозначающее временную
метку UNIX. То же относится к аргументам правил Min, Max или
Range, задающих минимальные и максимальные допустимые дату
и время.
$form->addDateTime('datetime', 'Дата и время:')
->setDefaultValue(new DateTime)
->addRule($form::Min, 'Дата должна быть не менее чем месячной давности.', new DateTime('-1 month'));
По умолчанию возвращает объект DateTimeImmutable. Методом
setFormat() можно задать текстовый формат
или временную метку:
$form->addDateTime('datetime')
->setFormat(DateTimeControl::FormatTimestamp);
addColor (string $name, $label=null): ColorPicker
Добавляет поле выбора цвета (класс ColorPicker). Цвет
возвращается строкой в формате #rrggbb. Если пользователь ничего
не выберет, возвращается чёрный #000000.
$form->addColor('color', 'Цвет:')
->setDefaultValue('#3C8ED7');
addHidden (string $name, mixed $default=null): HiddenField
Добавляет скрытое поле (класс HiddenField).
$form->addHidden('userid');
С помощью setNullable() можно добиться, чтобы вместо пустой строки
возвращался null. Метод addFilter() позволяет
изменить отправленное значение.
Хотя элемент скрыт, важно осознавать, что его значение всё равно может быть изменено или подделано злоумышленником. Всегда тщательно проверяйте все полученные значения на стороне сервера, чтобы предотвратить риски безопасности, связанные с манипуляцией данными.
addSubmit (string $name, $caption=null): SubmitButton
Добавляет кнопку отправки (класс SubmitButton).
$form->addSubmit('submit', 'Отправить');
Обработчик можно передать кнопке напрямую третьим
параметром $onSubmit вместо того, чтобы привязывать его к событию
onClick:
$form->addSubmit('submit', 'Отправить', function (SubmitButton $button, $data): void {
// ...
});
В форме может быть и больше одной кнопки отправки:
$form->addSubmit('register', 'Зарегистрироваться');
$form->addSubmit('cancel', 'Отменить');
Чтобы определить, по какой из них щёлкнули, используйте:
if ($form['register']->isSubmittedBy()) {
// ...
}
Если вы не хотите проверять всю форму при нажатии кнопки (например, для кнопок Отмена или Предпросмотр), используйте setValidationScope().
addButton (string $name, $caption=null): Button
Добавляет кнопку (класс Button), у которой нет функции отправки. Её можно использовать для других задач, например для вызова JavaScript-функции по щелчку.
$form->addButton('raise', 'Повысить зарплату')
->setHtmlAttribute('onclick', 'raiseSalary()');
addImageButton (string $name, ?string $src=null, ?string $alt=null): ImageButton
Добавляет кнопку отправки в виде картинки (класс ImageButton).
$form->addImageButton('submit', '/path/to/image.png', 'Отправить');
При использовании нескольких кнопок отправки определить, по какой из
них щёлкнули, можно через $form['submit']->isSubmittedBy().
addContainer (string|int $name): Container
Добавляет подформу (класс Container), то есть контейнер, в
который можно добавлять другие элементы так же, как их добавляют в
форму. Работают и методы вроде setDefaults() или getValues().
$sub1 = $form->addContainer('first');
$sub1->addText('name', 'Ваше имя:');
$sub1->addEmail('email', 'Email:');
$sub2 = $form->addContainer('second');
$sub2->addText('name', 'Ваше имя:');
$sub2->addEmail('email', 'Email:');
Отправленные данные затем возвращаются в виде многомерной структуры:
[
'first' => [
'name' => /* ... */,
'email' => /* ... */,
],
'second' => [
'name' => /* ... */,
'email' => /* ... */,
],
]
Обзор настроек
У всех элементов мы можем вызвать следующие методы (полный обзор смотрите в документации API):
setDefaultValue($value) |
задаёт значение по умолчанию |
getValue() |
получает текущее значение |
setOmitted() |
Опущенные значения |
setDisabled() |
Отключение элементов |
Отрисовка:
setCaption($caption) |
меняет метку элемента |
setTranslator($translator) |
задаёт переводчик |
setHtmlAttribute($name, $value) |
задаёт HTML-атрибут элемента |
setHtmlId($id) |
задаёт HTML-атрибут id |
setOption($key, $value) |
задаёт параметры отрисовки |
Проверка:
setRequired() |
делает элемент обязательным |
addRule() |
добавляет правило проверки |
addCondition(), addConditionOn() |
задаёт условие проверки |
addError($message) |
добавляет сообщение об ошибке |
У элементов addText(), addPassword(), addTextArea(), addEmail(),
addInteger(), addFloat() можно вызвать следующие методы:
setNullable() |
задаёт, будет ли getValue() возвращать null вместо пустой строки |
setEmptyValue($value) |
задаёт особое значение, которое считается пустой строкой |
setMaxLength($length) |
задаёт максимально допустимое количество символов |
addFilter($filter) |
изменяет ввод |
Опущенные значения
Если значение, заполненное пользователем, нас не интересует, мы можем
через setOmitted() исключить его из результата метода
$form->getValues() или из данных, передаваемых обработчикам. Это
удобно для разных полей подтверждения пароля, антиспам-элементов и
т. п.
$form->addPassword('passwordVerify', 'Пароль ещё раз:')
->setRequired('Введите пароль ещё раз для проверки опечатки')
->addRule($form::Equal, 'Пароли не совпадают', $form['password'])
->setOmitted();
Отключение элементов
Элементы можно отключить через setDisabled(). Отключённый элемент
пользователь не может редактировать.
$form->addText('username', 'Имя пользователя:')
->setDisabled();
Отключённые элементы браузер вообще не отправляет на сервер, так что
в данных, которые возвращает функция $form->getValues(), вы их не
найдёте. Однако если задать setOmitted(false), Nette включит в эти данные
их значение по умолчанию.
При вызове setDisabled() значение элемента очищается из
соображений безопасности. Если вы задаёте значение по умолчанию,
делать это нужно после отключения:
$form->addText('username', 'Имя пользователя:')
->setDisabled()
->setDefaultValue($userName);
Альтернатива отключённым элементам – элементы с HTML-атрибутом
readonly, которые браузер на сервер отправляет. Хотя элемент
доступен только для чтения, важно осознавать, что его значение всё
равно может быть изменено или подделано злоумышленником.
Собственные элементы
Кроме широкого набора встроенных элементов формы, в форму можно добавлять собственные:
$form->addComponent(new DateInput('Дата:'), 'date');
// альтернативная запись: $form['date'] = new DateInput('Дата:');
Как написать такой элемент, включая чтение отправленных данных,
проверку и отрисовку, описано в отдельной главе. Там же вы узнаете о
методах-расширениях, которые позволяют создать собственный метод
добавления вроде $form->addZip().
Низкоуровневые поля
Можно использовать и элементы, которые записаны только в шаблоне и не
добавлены в форму ни одним из методов $form->addXyz(). Например, когда
мы выводим записи из базы данных и заранее не знаем, сколько их будет и
какие у них будут ID, а хотим для каждой строки показать флажок или
радиокнопку, мы можем просто написать это в шаблоне:
{foreach $items as $item}
<p><input type=checkbox name="sel[]" value={$item->id}> {$item->name}</p>
{/foreach}
А после отправки получим значение:
$data = $form->getHttpData($form::DataText, 'sel[]');
$data = $form->getHttpData($form::DataText | $form::DataKeys, 'sel[]');
где первый параметр – тип элемента (DataFile для type=file,
DataLine для однострочных полей вроде text, password,
email и т. п. и DataText для всех остальных), а второй параметр
sel[] соответствует HTML-атрибуту name. Тип элемента можно сочетать со
значением DataKeys, которое сохраняет ключи элементов. Особенно это
полезно для select, radioList и checkboxList.
Существенно, что getHttpData() возвращает очищенное значение. В
данном случае это всегда будет массив корректных UTF-8-строк независимо
от того, что попытается отправить на сервер злоумышленник. Это
аналогично прямой работе с $_POST или $_GET, но с той
существенной разницей, что вы всегда получаете чистые данные, как вы
привыкли у стандартных элементов форм Nette.