There’s a widget in Yii2 framework, that is used for displaying form fields. The class
of this widget called ActiveField (yii\widgets\ActiveField).
ActiveField is used exclusively together with the ActiveForm
widget, because some of its
properties must reference an ActiveForm object.
ActiveField instances are created by calling the field() method on an ActiveForm object.
By default an instance of yii\widgets\ActiveField is created, but the class can be overridden through
the $fieldClass property of ActiveForm.
The field() method requires two mandatory parameters:
public function field($model, $attribute, $options = [])
$model— the model holding the property we want to associate with this field.$attribute— the name of that property.
Example 1
Code:
<?= $form->field($model, 'first_name'); ?>
Result:
<div class="form-group field-signupform-first_name required">
<label class="control-label" for="signupform-first_name">First Name</label>
<input type="text" id="signupform-first_name" class="form-control" name="SignUpForm[first_name]" aria-required="true">
<div class="help-block"></div>
</div>
The ActiveField class has a template property that defines the structure of the HTML block. Its default value is:
public $template = "{label}\n{input}\n{hint}\n{error}";
As the template shows, the block consists of four consecutive tags separated by newlines, all wrapped in a parent container.
How rendering works
The HTML block itself is produced by the render() method, which returns a ready string of markup. The ActiveField
class also has a magic __toString() method that calls the same render(), which means the result can be printed with
echo $active_form_object.
Rendering replaces the placeholders from $template with the HTML elements stored in the $parts[] array under the
corresponding keys:
$parts['{label}']
$parts['{input}']
$parts['{hint}']
$parts['{error}']
If an element is missing from $parts[], it is generated by one of these methods:
| Element | Method |
|---|---|
{label} |
label($label = null, $options = []) |
{input} |
input($type, $options = []),textInput($options = []),hiddenInput($options = []),passwordInput($options = []),fileInput($options = []),textarea($options = []),radio($options = [], $enclosedByLabel = true),checkbox($options = [], $enclosedByLabel = true),dropDownList($items, $options = []),listBox($items, $options = []),checkboxList($items, $options = []),radioList($items, $options = []) |
{hint} |
hint($content, $options = []) |
{error} |
error($options = []) |
We can either put the elements into the array in advance, or call the listed methods manually so that the elements get generated. The second option is interesting because it lets us pass extra parameters (such as CSS classes or tag attributes).
If the {input} element was not set manually through one of these methods, textInput() is called before rendering.
Everything passed in the $options array becomes attributes and values of the specific tag. On top of that, each element
uses a default set of attributes.
| Element | Property | Default value |
|---|---|---|
{label} |
$labelOptions |
['class' => 'control-label'] |
{input} |
$inputOptions |
['class' => 'form-control'] |
{hint} |
$hintOptions |
['class' => 'hint-block'] |
{error} |
$errorOptions |
['class' => 'help-block'] |
These properties come in handy when we want to override all CSS classes for, say, the container that displays errors.
Parent container
All elements of the block template:
public $template = "{label}\n{input}\n{hint}\n{error}";
are wrapped in a parent tag, which is a <div> by default.
ActiveField has an options property — an array of attributes and values for the parent container tag. Its default
value is ['class' => 'form-group'].
For example, here’s how we can change a class value for the parent container of the field block:
$form->field($model, 'name', [
'options' => ['class' => 'hello'],
]);
To get rid of some of the default attributes, use:
'options' => [
'class' => null,
]
There is also a trick: passing 'tag' => false removes the parent container entirely.
Andrew Dorokhov