Form Controls
Overview of standard form controls.
addText (string|int $name, $label=null, $cols=null, ?int $maxLength=null): TextInput
Adds a single-line text input field (class TextInput). If the user does not fill in the
field, it returns an empty string ''
, or use setNullable()
to make it return null
instead.
$form->addText('name', 'Name:')
->setRequired()
->setNullable();
Automatically validates UTF-8, trims leading and trailing whitespace, and removes line breaks that could be sent by an attacker.
The maximum length can be limited using setMaxLength()
. The addFilter() method allows modifying the value
entered by the user.
Using setHtmlType()
, you can change the visual appearance of the text field to types like search
,
tel
, or url
as defined in the specification. Remember that changing the type
is purely visual and does not replace validation functionality. For the url
type, it's advisable to add a specific
URL validation rule.
For other input types like number
, range
, email
, date
,
datetime-local
, time
, and color
, use specialized methods such as addInteger, addFloat, addEmail, addDate, addTime, addDateTime, and addColor, which provide server-side validation. The types month
and week
are
not yet fully supported by all browsers.
An “empty value” can be set for the control. This acts somewhat like a default value, but if the user doesn't change it,
the control returns an empty string or null
.
$form->addText('phone', 'Phone:')
->setHtmlType('tel')
->setEmptyValue('+420');
addTextArea (string|int $name, $label=null): TextArea
Adds a multi-line text input field (class TextArea). If the user doesn't fill in the field,
it returns an empty string ''
, or use setNullable()
to make it return null
instead.
$form->addTextArea('note', 'Note:')
->addRule($form::MaxLength, 'Your note is way too long', 10000);
Automatically validates UTF-8 and normalizes line endings to \n
. Unlike the single-line input field, no
whitespace trimming occurs.
The maximum length can be limited using setMaxLength()
. The addFilter() method allows modifying the
user-entered value. An empty value can be set using setEmptyValue()
.
addInteger (string|int $name, $label=null): TextInput
Adds an input field for entering an integer (class TextInput). Returns either an integer or
null
if the user enters nothing.
$form->addInteger('year', 'Year:')
->addRule($form::Range, 'The year must be between %d and %d.', [1900, 2023]);
The control renders as <input type="number">
. Using the setHtmlType()
method, you can change
the type to range
for display as a slider, or to text
if you prefer a standard text field without the
special behavior of the number
type.
addFloat (string|int $name, $label=null): TextInput
Adds an input field for entering a floating-point number (class TextInput). Returns either a float or
null
if the user enters nothing.
$form->addFloat('level', 'Level:')
->setDefaultValue(0.0) // Explicitly set float default
->addRule($form::Range, 'The level must be between %f and %f.', [0.0, 100.0]); // Use float range and %f
The control renders as <input type="number">
. Using the setHtmlType()
method, you can change
the type to range
for display as a slider, or to text
if you prefer a standard text field without the
special behavior of the number
type.
Nette and the Chrome browser accept both a comma and a dot as decimal separators. To enable this functionality in Firefox as
well, it is recommended to set the lang
attribute either for the specific control or for the entire page, for
example, <html lang="en">
.
addEmail (string|int $name, $label=null, int $maxLength=255): TextInput
Adds an input field for entering an email address (class TextInput). If the user doesn't fill in the
field, it returns an empty string ''
, or use setNullable()
to make it return null
instead.
$form->addEmail('email', 'E-mail:');
Validates that the value is a valid email address. It does not check if the domain actually exists, only the syntax is verified. Automatically validates UTF-8 and trims leading and trailing whitespace.
The maximum length can be limited using setMaxLength()
. The addFilter() method allows modifying the
user-entered value. An empty value can be set using setEmptyValue()
.
addPassword (string|int $name, $label=null, $cols=null, ?int $maxLength=null): TextInput
Adds a password input field (class TextInput).
$form->addPassword('password', 'Password:')
->setRequired()
->addRule($form::MinLength, 'Password must be at least %d characters long', 8)
->addRule($form::Pattern, 'Password must contain a number', '.*[0-9].*');
When the form is redisplayed, the field will be empty. Automatically validates UTF-8, trims leading and trailing whitespace, and removes line breaks that could be sent by an attacker.
addCheckbox (string|int $name, $caption=null): Checkbox
Adds a checkbox (class Checkbox). Returns
true
or false
, depending on whether it is checked.
$form->addCheckbox('agree', 'I agree with terms')
->setRequired('You must agree with our terms');
addCheckboxList (string|int $name, $label=null, ?array $items=null): CheckboxList
Adds a list of checkboxes for selecting multiple items (class CheckboxList). Returns an array of the keys
of the selected items. The getSelectedItems()
method returns the values instead of keys.
$form->addCheckboxList('colors', 'Colors:', [
'r' => 'red',
'g' => 'green',
'b' => 'blue',
]);
Pass the array of offered items as the third parameter or using the setItems()
method.
Use setDisabled(['r', 'g'])
to disable individual items.
The control automatically checks that no forgery occurred and that the selected items are indeed among the offered ones and
were not disabled. The getRawValue()
method can be used to retrieve submitted items without this
important check.
When setting default selected items, it also checks that they are among the offered ones, otherwise it throws an exception.
This check can be disabled using checkDefaultValue(false)
.
If you are submitting the form using the GET
method, you can choose a more compact data transfer method that saves
query string size. Activate it by setting an HTML attribute on the form:
$form->setHtmlAttribute('data-nette-compact');
addRadioList (string|int $name, $label=null, ?array $items=null): RadioList
Adds radio buttons (class RadioList).
Returns the key of the selected item, or null
if the user selected nothing. The getSelectedItem()
method
returns the value instead of the key.
$sex = [
'm' => 'male',
'f' => 'female',
];
$form->addRadioList('gender', 'Gender:', $sex);
Pass the array of offered items as the third parameter or using the setItems()
method.
Use setDisabled(['m'])
to disable individual items.
The control automatically checks that no forgery occurred and that the selected item is indeed one of the offered ones and was
not disabled. The getRawValue()
method can be used to retrieve the submitted item without this important check.
When setting the default selected item, it also checks that it is one of the offered ones, otherwise it throws an exception.
This check can be disabled using checkDefaultValue(false)
.
addSelect (string|int $name, $label=null, ?array $items=null, ?int $size=null): SelectBox
Adds a select box (class SelectBox).
Returns the key of the selected item, or null
if the user selected nothing. The getSelectedItem()
method
returns the value instead of the key.
$countries = [
'CZ' => 'Czech Republic',
'SK' => 'Slovakia',
'GB' => 'United Kingdom',
];
$form->addSelect('country', 'Country:', $countries)
->setDefaultValue('SK');
Pass the array of offered items as the third parameter or using the setItems()
method. Items can also be a
two-dimensional array (representing optgroups):
$countries = [
'Europe' => [
'CZ' => 'Czech Republic',
'SK' => 'Slovakia',
'GB' => 'United Kingdom',
],
'CA' => 'Canada',
'US' => 'USA',
'?' => 'other',
];
In select boxes, the first item often has a special meaning, serving as a prompt to action. Use the setPrompt()
method to add such an item.
$form->addSelect('country', 'Country:', $countries)
->setPrompt('Choose a country');
Use setDisabled(['CZ', 'SK'])
to disable individual items.
The control automatically checks that no forgery occurred and that the selected item is indeed one of the offered ones and was
not disabled. The getRawValue()
method can be used to retrieve the submitted item without this important check.
When setting the default selected item, it also checks that it is one of the offered ones, otherwise it throws an exception.
This check can be disabled using checkDefaultValue(false)
.
addMultiSelect (string|int $name, $label=null, ?array $items=null, ?int $size=null): MultiSelectBox
Adds a select box for selecting multiple items (class MultiSelectBox). Returns an array of the
keys of the selected items. The getSelectedItems()
method returns the values instead of keys.
$form->addMultiSelect('countries', 'Countries:', $countries);
Pass the array of offered items as the third parameter or using the setItems()
method. Items can also be a
two-dimensional array.
Use setDisabled(['CZ', 'SK'])
to disable individual items.
The control automatically checks that no forgery occurred and that the selected items are indeed among the offered ones and
were not disabled. The getRawValue()
method can be used to retrieve submitted items without this
important check.
When setting default selected items, it also checks that they are among the offered ones, otherwise it throws an exception.
This check can be disabled using checkDefaultValue(false)
.
addUpload (string|int $name, $label=null): UploadControl
Adds a file upload field (class UploadControl). Returns a FileUpload object, even if the user did not upload any file, which
can be checked using the FileUpload::hasFile()
method.
$form->addUpload('avatar', 'Avatar:')
->addRule($form::Image, 'Avatar must be JPEG, PNG, GIF, WebP or AVIF.')
->addRule($form::MaxFileSize, 'Maximum size is 1 MB.', 1024 * 1024);
If the file fails to upload correctly, the form is not successfully submitted, and an error is displayed. That is, upon
successful submission, it is not necessary to check the FileUpload::isOk()
method.
Never trust the original file name returned by the FileUpload::getName()
method; the client could have sent a
malicious file name with the intent to damage or hack your application.
The MimeType
and Image
rules detect the required type based on the file's signature and do not
verify its integrity. Whether an image is corrupted can be determined, for example, by attempting to load it.
addMultiUpload (string|int $name, $label=null): UploadControl
Adds a field for uploading multiple files at once (class UploadControl). Returns an array of FileUpload objects. The FileUpload::hasFile()
method
for each of them will return true
.
$form->addMultiUpload('files', 'Files:')
->addRule($form::MaxLength, 'Maximum of %d files can be uploaded.', 10); // Added period
If any file fails to upload correctly, the form is not successfully submitted, and an error is displayed. That is, upon
successful submission, it is not necessary to check the FileUpload::isOk()
method for each file.
Never trust the original file names returned by the FileUpload::getName()
method; the client could have sent
malicious file names with the intent to damage or hack your application.
The MimeType
and Image
rules detect the required type based on the file's signature and do not
verify its integrity. Whether an image is corrupted can be determined, for example, by attempting to load it.
addDate (string|int $name, $label=null): DateTimeControl
Adds a field that allows the user to easily enter a date consisting of year, month, and day (class DateTimeControl).
As a default value, it accepts objects implementing the DateTimeInterface
, a string containing time, or a number
representing a UNIX timestamp. The same applies to the arguments of the Min
, Max
, or Range
rules, which define the minimum and maximum allowed dates.
$form->addDate('date', 'Date:')
->setDefaultValue(new DateTime)
->addRule($form::Min, 'The date must be at least one month old.', new DateTime('-1 month'));
By default, it returns a DateTimeImmutable
object. Using the setFormat()
method, you can specify a text format or a timestamp:
$form->addDate('date', 'Date:')
->setFormat('Y-m-d');
addTime (string|int $name, $label=null, bool $withSeconds=false): DateTimeControl
Adds a field that allows the user to easily enter a time consisting of hours, minutes, and optionally seconds (class DateTimeControl).
As a default value, it accepts objects implementing the DateTimeInterface
, a string containing time, or a number
representing a UNIX timestamp. Only the time information from these inputs is used; the date is ignored. The same applies to the
arguments of the Min
, Max
, or Range
rules, which define the minimum and maximum allowed
times. If the set minimum value is higher than the maximum, a time range spanning midnight is created.
$form->addTime('time', 'Time:', withSeconds: true)
->addRule($form::Range, 'Time must be between %s and %s.', ['12:30', '13:30']); // Use %s for time strings
By default, it returns a DateTimeImmutable
object (with the date set to January 1, year 1). Using the
setFormat()
method, you can specify a text format:
$form->addTime('time', 'Time:')
->setFormat('H:i');
addDateTime (string|int $name, $label=null, bool $withSeconds=false): DateTimeControl
Adds a field that allows the user to easily enter both date and time, consisting of year, month, day, hours, minutes, and optionally seconds (class DateTimeControl).
As a default value, it accepts objects implementing the DateTimeInterface
, a string containing time, or a number
representing a UNIX timestamp. The same applies to the arguments of the Min
, Max
, or Range
rules, which define the minimum and maximum allowed date and time.
$form->addDateTime('datetime', 'Date and Time:')
->setDefaultValue(new DateTime)
->addRule($form::Min, 'The date must be at least one month old.', new DateTime('-1 month'));
By default, it returns a DateTimeImmutable
object. Using the setFormat()
method, you can specify a text format or a timestamp:
$form->addDateTime('datetime')
->setFormat(DateTimeControl::FormatTimestamp);
addColor (string|int $name, $label=null): ColorPicker
Adds a color picker field (class ColorPicker). The color is returned as a
string in the format #rrggbb
. If the user does not make a selection, it returns black #000000
.
$form->addColor('color', 'Color:')
->setDefaultValue('#3C8ED7');
addHidden (string|int $name, ?string $default=null): HiddenField
Adds a hidden field (class HiddenField).
$form->addHidden('userid');
Use setNullable()
to make it return null
instead of an empty string. The addFilter() method allows modifying the
submitted value.
Although the control is hidden, it is important to realize that its value can still be modified or spoofed by an attacker. Always thoroughly verify and validate all received values on the server side to prevent security risks associated with data manipulation.
addSubmit (string|int $name, $caption=null): SubmitButton
Adds a submit button (class SubmitButton).
$form->addSubmit('submit', 'Submit');
It is possible to have more than one submit button in the form:
$form->addSubmit('register', 'Register');
$form->addSubmit('cancel', 'Cancel');
To determine which one was clicked, use:
if ($form['register']->isSubmittedBy()) {
// ...
}
If you do not want to validate the entire form when a button is pressed (for example, for Cancel or Preview buttons), use setValidationScope().
addButton (string|int $name, $caption): Button
Adds a button (class Button) that does not have a submit function. It can therefore be used for other functions, e.g., calling a JavaScript function on click.
$form->addButton('raise', 'Raise salary')
->setHtmlAttribute('onclick', 'raiseSalary()');
addImageButton (string|int $name, ?string $src=null, ?string $alt=null): ImageButton
Adds a submit button in the form of an image (class ImageButton).
$form->addImageButton('submit', '/path/to/image.png', 'Submit');
When using multiple submit buttons, you can determine which one was clicked using
$form['submit']->isSubmittedBy()
.
addContainer (string|int $name): Container
Adds a sub-form (class Container), or a container,
into which other controls can be added in the same way as they are added to the form. Methods like setDefaults()
or
getValues()
work as well.
$sub1 = $form->addContainer('first');
$sub1->addText('name', 'Your name:');
$sub1->addEmail('email', 'Email:');
$sub2 = $form->addContainer('second');
$sub2->addText('name', 'Your name:');
$sub2->addEmail('email', 'Email:');
The submitted data is then returned as a multi-dimensional structure:
[
'first' => [
'name' => /* ... */,
'email' => /* ... */,
],
'second' => [
'name' => /* ... */,
'email' => /* ... */,
],
]
Overview of Settings
For all controls, we can call the following methods (see the API documentation for a complete overview):
setDefaultValue($value) |
sets the default value |
getValue() |
get the current value |
setOmitted() |
Omitted Values |
setDisabled() |
Disabling Inputs |
Rendering:
setCaption($caption) |
changes the control's label |
setTranslator($translator) |
sets the translator |
setHtmlAttribute($name, $value) |
sets an HTML attribute for the element |
setHtmlId($id) |
sets the HTML attribute id |
setHtmlType($type) |
sets the HTML attribute type |
setHtmlName($name) |
sets the HTML attribute name |
setOption($key, $value) |
sets rendering options |
Validation:
setRequired() |
makes the control required |
addRule() |
adds a validation rule |
addCondition() , addConditionOn() |
sets a validation condition |
addError($message) |
adds an error message |
For controls addText()
, addPassword()
, addTextArea()
, addEmail()
,
addInteger()
, the following methods can be called:
setNullable() |
sets whether getValue() returns null instead of an empty string |
setEmptyValue($value) |
sets a special value that is considered an empty string |
setMaxLength($length) |
sets the maximum allowed number of characters |
addFilter($filter) |
modifies input |
Omitted Values
If we are not interested in the value filled in by the user, we can use setOmitted()
to exclude it from the result
of the $form->getValues()
method or from the data passed to handlers. This is useful for various password
confirmation fields, anti-spam controls, etc.
$form->addPassword('passwordVerify', 'Password again:')
->setRequired('Fill your password again to check for typo')
->addRule($form::Equal, 'Passwords do not match', $form['password'])
->setOmitted();
Disabling Inputs
Controls can be disabled using setDisabled()
. A disabled control cannot be edited by the user.
$form->addText('username', 'User name:')
->setDisabled();
Disabled controls are not sent by the browser to the server at all, so you won't find them in the data returned by the
$form->getValues()
function. However, if you set setOmitted(false)
, Nette will include their default
value in this data.
When setDisabled()
is called, the control's value is cleared for security reasons. If you are setting a
default value, it is necessary to do so after disabling it:
$form->addText('username', 'User name:')
->setDisabled()
->setDefaultValue($userName);
An alternative to disabled controls are controls with the HTML readonly
attribute, which the browser does send to
the server. Although the control is read-only, it is important to realize that its value can still be modified or spoofed
by an attacker.
Custom Controls
Besides the wide range of built-in form controls, you can add custom controls to the form in this way:
$form->addComponent(new DateInput('Date:'), 'date');
// alternative syntax: $form['date'] = new DateInput('Date:');
The form is a descendant of the Container class, and individual controls are descendants of the Component class.
There is a way to define new form methods for adding custom controls (e.g., $form->addZip()
). These are called
extension methods. The disadvantage is that code completion in editors will not work for them.
use Nette\Forms\Container;
// adds method addZip(string $name, ?string $label = null)
Container::extensionMethod('addZip', function (Container $form, string $name, ?string $label = null) {
return $form->addText($name, $label)
->addRule($form::Pattern, 'At least 5 numbers', '[0-9]{5}');
});
// usage
$form->addZip('zip', 'ZIP code:');
Low-Level Fields
It's also possible to use controls that are only written in the template and not added to the form using any of the
$form->addXyz()
methods. For example, when listing records from a database where we don't know in advance how many
there will be or what their IDs will be, and we want to display a checkbox or radio button for each row, we can simply code it in
the template:
{foreach $items as $item}
<p><input type=checkbox name="sel[]" value={$item->id}> {$item->name}</p>
{/foreach}
And after submission, we retrieve the value:
$data = $form->getHttpData($form::DataText, 'sel[]');
$data = $form->getHttpData($form::DataText | $form::DataKeys, 'sel[]');
where the first parameter is the element type (DataFile
for type=file
, DataLine
for
single-line inputs like text
, password
, email
, etc., and DataText
for all
others) and the second parameter sel[]
corresponds to the HTML name attribute. We can combine the element type with
the DataKeys
value, which preserves the keys of the elements. This is particularly useful for select
,
radioList
, and checkboxList
.
Crucially, getHttpData()
returns a sanitized value. In this case, it will always be an array of valid
UTF-8 strings, regardless of what an attacker might try to submit to the server. This is analogous to working directly with
$_POST
or $_GET
, but with the significant difference that it always returns clean data, just as you are
accustomed to with standard Nette form controls.