Forms Rendering
Forms' appearances can differ greatly. In fact, there are two extremes. One side is the need to render a set of very similar forms all over again, with little to none effort. Usually administrations and back-ends.
The other side is tiny sweet forms, each one being a piece of art. Their layout can best be written in HTML. Of course, besides those extremes, there are many forms just in between.
Default Renderer
Renderer automatically renders a form. It's set with setRenderer()
method on a form and it gains control when
calling $form->render()
. If we set no custom renderer, Nette\Forms\Rendering\DefaultFormRenderer
is used. All you have to write is:
or in Latte:
and the form is alive. All input fields are rendered into an HTML table. The output could look like this:
Nicely formatted, isn't it? :-)
It's up to you, whether to use a table or not, and many web designers prefer different markups, for example a list. We may
configure DefaultFormRenderer
so it would not render into a table at all. We just have to set proper $wrappers. The first
index always represents an area and the second one it's element. All respective areas are shown in the picture:

By default a group of controls
is wrapped in <table>
, and every pair
is a table
row <tr>
containing a pair of label
and control
(cells <th>
and
<td>
). Let's change all those wrapper elements. We will wrap controls
into
<dl>
, leave pair
by itself, put label
into <dt>
and wrap
control
into <dd>
:
Results into the following snippet:
Wrappers can affect many attributes. For example:
- add special CSS classes to each form input
- distinguish between odd and even lines
- make required and optional draw differently
- set, whether error messages are shown above the form or close to each element
Bootstrap Support
You can find examples of configuration forms for Twitter Bootstrap 2, Bootstrap 3 and Bootstrap 4
Latte
Templating engine Latte makes it much easier to render forms and their elements:
The {form}
or <form n:name>
tag starts rendering of given form. It also creates a local
variable $form
with a form object. The closing {/form}
or </form>
tag renders all
undrawn hidden fields before completes the form.
{input}
tag renders any element including select boxes and textareas. {label}
is optionally paired
tag, ie. {label}Age{/label}
, in that case the text is translated too. Tag {inputError}
prints error
message for form input.
It's also possible to „breathe life“ into a raw HTML input with n:name
attribute tag, which links it with the
form input using its identification:
If you only need to render the inner content of a form without <form>
&
</form>
HTML tags, for example, in an AJAX request, you can open and close the form with
{formContext formName} … {/formContext}
. It works similarly to {form}
in a logical sense, here it
allows you to use other tags to draw form elements, but at the same time it doesn't draw anything.
Code Proposal {formPrint}
You can also generate Latte code for a form using the {formPrint}
tag. If you
place it in a template, the code of form is displayed instead of the normal template. Then simply select and copy the code into
your project.
Manual Rendering
You can render forms manually for better control over the generated code. Place the form inside {form myForm}
and
{/form}
pair tags. Inputs can be rendered using {input myInput}
tag, which renders the input, and
{label myInput /}
, which renders its the label.
You can also connect a form with a template easily by using n:name
attribute.
You can also use n:name
with <select>
, <button>
or
<textarea>
elements and the content.
You can render RadioList, Checkbox or CheckboxList by HTML elements individually. This is called partial rendering:
Or you can use basic tags {input gender:$key}
and {label gender:$key}
. The trick is using the colon.
For a simple checkbox, use {input myCheckbox:}
.
Tag formContainer
helps with rendering of inputs inside a form container.
How to set more attributes to HTML elements? Methods getControl()
and getLabel()
return element as a
Nette\Utils\Html
objects, which can be easily adjusted.
In Latte:
Grouping Inputs
Input fields can be grouped into visual field-sets by creating a group:
Creating new group activates it – all elements added further are added to this group. You may build a form like this:
HTML Attributes
You can set any HTML attributes to form controls using setHtmlAttribute(string $name, $value = true)
:
Setting input type:
We can set HTML attribute to individual items in radio or checkbox lists with different values for each of them. Note the colon
after style:
to ensure that the value is selected by key:
Renders:
For a logical HTML attribute (which has no value, such as readonly
), you can use a question mark:
Renders:
For selectboxes, the setHtmlAttribute()
method sets the attributes of the <select>
element. If
we want to set the attributes for each <option>
, we will use the method addOptionAttributes()
.
Also, the colon and question mark used above work:
Renders:
Other Setting
Setting description (rendered after the input by default):
If we want to place HTML content into it, we use Html class.
Html element can be also used instead of label: $form->addCheckbox('conditions', $label)
.
Without Latte
Each element has getLabel()
and getControl()
methods which return HTML code of label and the element
itself. Nette provides getter and setter property access as if you are accessing the attribute itself.
Event onRender
Just before the form is rendered, we can have our code invoked. This can, for example, add HTML classes to the form elements
for proper display. We add the code to the onRender
array: