1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\widgets;
use yii\base\Component;
use yii\base\InvalidParamException;
use yii\helpers\Html;
/**
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class ActiveField extends Component
{
/**
* @var string the tag name. Defaults to 'div'.
*/
public $tag;
/**
* @var ActiveForm
*/
public $form;
/**
* @var \yii\base\Model
*/
public $model;
/**
* @var string
*/
public $attribute;
/**
* @var array
*/
public $options = array(
'tag' => 'div',
'class' => 'yii-field',
);
public $autoFieldCssClass = true;
/**
* @var string the default CSS class that indicates an input is required.
*/
public $requiredCssClass = 'required';
/**
* @var string the default CSS class that indicates an input has error.
*/
public $errorCssClass = 'error';
/**
* @var string the default CSS class that indicates an input validated successfully.
*/
public $successCssClass = 'success';
/**
* @var string the default CSS class that indicates an input is currently being validated.
*/
public $validatingCssClass = 'validating';
public $layout = "{label}\n{input}\n{error}";
public $errorOptions = array('tag' => 'span', 'class' => 'yii-error-message');
public $labelOptions = array('class' => 'control-label');
public function begin()
{
$options = $this->options;
$this->tag = isset($options['tag']) ? $options['tag'] : 'div';
unset($options['tag']);
$class = isset($options['class']) ? array($options['class']) : array();
if ($this->autoFieldCssClass) {
$class[] = 'field-' . Html::getInputId($this->model, $this->attribute);
}
if ($this->model->isAttributeRequired($this->attribute)) {
$class[] = $this->requiredCssClass;
}
if ($this->model->hasErrors($this->attribute)) {
$class[] = $this->errorCssClass;
}
if ($class !== array()) {
$options['class'] = implode(' ', $class);
}
return Html::beginTag($this->tag, $options);
}
public function end()
{
return Html::endTag($this->tag);
}
public function label($options = null)
{
if ($options === null) {
$options = $this->labelOptions;
}
return Html::activeLabel($this->model, $this->attribute, $options);
}
public function error($options = null)
{
if ($options === null) {
$options = $this->errorOptions;
}
$attribute = Html::getAttributeName($this->attribute);
$error = $this->model->getFirstError($attribute);
if ($error === null) {
$options['style'] = isset($options['style']) ? rtrim($options['style'], ';') . '; display:none' : 'display:none';
}
$tag = isset($options['tag']) ? $options['tag'] : 'span';
unset($options['tag']);
return Html::tag($tag, Html::encode($error), $options);
}
protected function render($input)
{
return $this->begin() . "\n" . strtr($this->layout, array(
'{input}' => $input,
'{label}' => $this->label(),
'{error}' => $this->error(),
)) . $this->end();
}
/**
* Generates an input tag for the given model attribute.
* @param string $type the input type (e.g. 'text', 'password')
* @param array $options the tag options in terms of name-value pairs. These will be rendered as
* the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
* @return string the generated input tag
*/
public function input($type, $options = array())
{
return $this->render(Html::activeInput($type, $this->model, $this->attribute, $options));
}
/**
* Generates a text input tag for the given model attribute.
* This method will generate the "name" and "value" tag attributes automatically for the model attribute
* unless they are explicitly specified in `$options`.
* @param array $options the tag options in terms of name-value pairs. These will be rendered as
* the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
* @return string the generated input tag
*/
public function textInput($options = array())
{
return $this->render(Html::activeTextInput($this->model, $this->attribute, $options));
}
/**
* Generates a hidden input tag for the given model attribute.
* This method will generate the "name" and "value" tag attributes automatically for the model attribute
* unless they are explicitly specified in `$options`.
* @param array $options the tag options in terms of name-value pairs. These will be rendered as
* the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
* @return string the generated input tag
*/
public function hiddenInput($options = array())
{
return $this->render(Html::activeHiddenInput($this->model, $this->attribute, $options));
}
/**
* Generates a password input tag for the given model attribute.
* This method will generate the "name" and "value" tag attributes automatically for the model attribute
* unless they are explicitly specified in `$options`.
* @param array $options the tag options in terms of name-value pairs. These will be rendered as
* the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
* @return string the generated input tag
*/
public function passwordInput($options = array())
{
return $this->render(Html::activePasswordInput($this->model, $this->attribute, $options));
}
/**
* Generates a file input tag for the given model attribute.
* This method will generate the "name" and "value" tag attributes automatically for the model attribute
* unless they are explicitly specified in `$options`.
* @param array $options the tag options in terms of name-value pairs. These will be rendered as
* the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
* @return string the generated input tag
*/
public function fileInput($options = array())
{
return $this->render(Html::activeFileInput($this->model, $this->attribute, $options));
}
/**
* Generates a textarea tag for the given model attribute.
* The model attribute value will be used as the content in the textarea.
* @param array $options the tag options in terms of name-value pairs. These will be rendered as
* the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
* @return string the generated textarea tag
*/
public function textarea($options = array())
{
return $this->render(Html::activeTextarea($this->model, $this->attribute, $options));
}
/**
* Generates a radio button tag for the given model attribute.
* This method will generate the "name" tag attribute automatically unless it is explicitly specified in `$options`.
* This method will generate the "checked" tag attribute according to the model attribute value.
* @param string $value the value tag attribute. If it is null, the value attribute will not be rendered.
* @param array $options the tag options in terms of name-value pairs. The following options are specially handled:
*
* - uncheck: string, the value associated with the uncheck state of the radio button. If not set,
* it will take the default value '0'. This method will render a hidden input so that if the radio button
* is not checked and is submitted, the value of this attribute will still be submitted to the server
* via the hidden input.
*
* The rest of the options will be rendered as the attributes of the resulting tag. The values will
* be HTML-encoded using [[encode()]]. If a value is null, the corresponding attribute will not be rendered.
*
* @return string the generated radio button tag
*/
public function radio($value = '1', $options = array())
{
return $this->render(Html::activeRadio($this->model, $this->attribute, $value, $options));
}
public function radioAlt($value = '1', $options = array())
{
$label = Html::encode($this->model->getAttributeLabel($this->attribute));
return $this->begin() . "\n"
. Html::label(Html::activeRadio($this->model, $this->attribute, $value, $options) . ' ' . $label) . "\n"
. $this->error() . "\n"
. $this->end();
}
/**
* Generates a checkbox tag for the given model attribute.
* This method will generate the "name" tag attribute automatically unless it is explicitly specified in `$options`.
* This method will generate the "checked" tag attribute according to the model attribute value.
* @param string $value the value tag attribute. If it is null, the value attribute will not be rendered.
* @param array $options the tag options in terms of name-value pairs. The following options are specially handled:
*
* - uncheck: string, the value associated with the uncheck state of the radio button. If not set,
* it will take the default value '0'. This method will render a hidden input so that if the radio button
* is not checked and is submitted, the value of this attribute will still be submitted to the server
* via the hidden input.
*
* The rest of the options will be rendered as the attributes of the resulting tag. The values will
* be HTML-encoded using [[encode()]]. If a value is null, the corresponding attribute will not be rendered.
*
* @return string the generated checkbox tag
*/
public function checkbox($value = '1', $options = array())
{
return $this->render(Html::activeCheckbox($this->model, $this->attribute, $value, $options));
}
public function checkboxAlt($value = '1', $options = array())
{
$label = Html::encode($this->model->getAttributeLabel($this->attribute));
return $this->begin() . "\n"
. Html::label(Html::activeCheckbox($this->model, $this->attribute, $value, $options) . ' ' . $label) . "\n"
. $this->error() . "\n"
. $this->end();
}
/**
* Generates a drop-down list for the given model attribute.
* The selection of the drop-down list is taken from the value of the model attribute.
* @param array $items the option data items. The array keys are option values, and the array values
* are the corresponding option labels. The array can also be nested (i.e. some array values are arrays too).
* For each sub-array, an option group will be generated whose label is the key associated with the sub-array.
* If you have a list of data models, you may convert them into the format described above using
* [[\yii\helpers\ArrayHelper::map()]].
*
* Note, the values and labels will be automatically HTML-encoded by this method, and the blank spaces in
* the labels will also be HTML-encoded.
* @param array $options the tag options in terms of name-value pairs. The following options are specially handled:
*
* - prompt: string, a prompt text to be displayed as the first option;
* - options: array, the attributes for the select option tags. The array keys must be valid option values,
* and the array values are the extra attributes for the corresponding option tags. For example,
*
* ~~~
* array(
* 'value1' => array('disabled' => true),
* 'value2' => array('label' => 'value 2'),
* );
* ~~~
*
* - groups: array, the attributes for the optgroup tags. The structure of this is similar to that of 'options',
* except that the array keys represent the optgroup labels specified in $items.
*
* The rest of the options will be rendered as the attributes of the resulting tag. The values will
* be HTML-encoded using [[encode()]]. If a value is null, the corresponding attribute will not be rendered.
*
* @return string the generated drop-down list tag
*/
public function dropDownList($items, $options = array())
{
return $this->render(Html::activeDropDownList($this->model, $this->attribute, $items, $options));
}
/**
* Generates a list box.
* The selection of the list box is taken from the value of the model attribute.
* @param array $items the option data items. The array keys are option values, and the array values
* are the corresponding option labels. The array can also be nested (i.e. some array values are arrays too).
* For each sub-array, an option group will be generated whose label is the key associated with the sub-array.
* If you have a list of data models, you may convert them into the format described above using
* [[\yii\helpers\ArrayHelper::map()]].
*
* Note, the values and labels will be automatically HTML-encoded by this method, and the blank spaces in
* the labels will also be HTML-encoded.
* @param array $options the tag options in terms of name-value pairs. The following options are specially handled:
*
* - prompt: string, a prompt text to be displayed as the first option;
* - options: array, the attributes for the select option tags. The array keys must be valid option values,
* and the array values are the extra attributes for the corresponding option tags. For example,
*
* ~~~
* array(
* 'value1' => array('disabled' => true),
* 'value2' => array('label' => 'value 2'),
* );
* ~~~
*
* - groups: array, the attributes for the optgroup tags. The structure of this is similar to that of 'options',
* except that the array keys represent the optgroup labels specified in $items.
* - unselect: string, the value that will be submitted when no option is selected.
* When this attribute is set, a hidden field will be generated so that if no option is selected in multiple
* mode, we can still obtain the posted unselect value.
*
* The rest of the options will be rendered as the attributes of the resulting tag. The values will
* be HTML-encoded using [[encode()]]. If a value is null, the corresponding attribute will not be rendered.
*
* @return string the generated list box tag
*/
public function listBox($items, $options = array())
{
return $this->render(Html::activeListBox($this->model, $this->attribute, $items, $options));
}
/**
* Generates a list of checkboxes.
* A checkbox list allows multiple selection, like [[listBox()]].
* As a result, the corresponding submitted value is an array.
* The selection of the checkbox list is taken from the value of the model attribute.
* @param array $items the data item used to generate the checkboxes.
* The array keys are the labels, while the array values are the corresponding checkbox values.
* Note that the labels will NOT be HTML-encoded, while the values will.
* @param array $options options (name => config) for the checkbox list. The following options are specially handled:
*
* - unselect: string, the value that should be submitted when none of the checkboxes is selected.
* By setting this option, a hidden input will be generated.
* - separator: string, the HTML code that separates items.
* - item: callable, a callback that can be used to customize the generation of the HTML code
* corresponding to a single item in $items. The signature of this callback must be:
*
* ~~~
* function ($index, $label, $name, $checked, $value)
* ~~~
*
* where $index is the zero-based index of the checkbox in the whole list; $label
* is the label for the checkbox; and $name, $value and $checked represent the name,
* value and the checked status of the checkbox input.
* @return string the generated checkbox list
*/
public function checkboxList($items, $options = array())
{
return Html::activeCheckboxList($this->model, $this->attribute, $items, $options);
}
/**
* Generates a list of radio buttons.
* A radio button list is like a checkbox list, except that it only allows single selection.
* The selection of the radio buttons is taken from the value of the model attribute.
* @param array $items the data item used to generate the radio buttons.
* The array keys are the labels, while the array values are the corresponding radio button values.
* Note that the labels will NOT be HTML-encoded, while the values will.
* @param array $options options (name => config) for the radio button list. The following options are specially handled:
*
* - unselect: string, the value that should be submitted when none of the radio buttons is selected.
* By setting this option, a hidden input will be generated.
* - separator: string, the HTML code that separates items.
* - item: callable, a callback that can be used to customize the generation of the HTML code
* corresponding to a single item in $items. The signature of this callback must be:
*
* ~~~
* function ($index, $label, $name, $checked, $value)
* ~~~
*
* where $index is the zero-based index of the radio button in the whole list; $label
* is the label for the radio button; and $name, $value and $checked represent the name,
* value and the checked status of the radio button input.
* @return string the generated radio button list
*/
public function radioList($items, $options = array())
{
return Html::activeRadioList($this->model, $this->attribute, $items, $options);
}
}