ActiveField.php 15.9 KB
Newer Older
Qiang Xue committed
1 2 3 4 5 6 7 8 9 10
<?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;
Qiang Xue committed
11
use yii\base\InvalidParamException;
Qiang Xue committed
12 13 14 15 16 17 18 19
use yii\helpers\Html;

/**
 * @author Qiang Xue <qiang.xue@gmail.com>
 * @since 2.0
 */
class ActiveField extends Component
{
Qiang Xue committed
20 21 22 23
	/**
	 * @var string the tag name. Defaults to 'div'.
	 */
	public $tag;
Qiang Xue committed
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
	/**
	 * @var ActiveForm
	 */
	public $form;
	/**
	 * @var \yii\base\Model
	 */
	public $model;
	/**
	 * @var string
	 */
	public $attribute;
	/**
	 * @var array
	 */
	public $options;
	
	public function begin()
	{
Qiang Xue committed
43 44 45 46 47 48 49 50 51 52
		$options = $this->options === null ? $this->form->fieldOptions : $this->options;
		$this->tag = isset($options['tag']) ? $options['tag'] : 'div';
		unset($options['tag']);
		$class = isset($options['class']) ? array($options['class']) : array();
		if ($this->form->autoFieldCssClass) {
			$class[] = 'field-' . Html::getInputId($this->model, $this->attribute);
		}
		if ($this->model->isAttributeRequired($this->attribute)) {
			$class[] = $this->form->requiredCssClass;
		}
Qiang Xue committed
53
		if ($this->model->hasErrors($this->attribute)) {
Qiang Xue committed
54 55 56 57
			$class[] = $this->form->errorCssClass;
		}
		if ($class !== array()) {
			$options['class'] = implode(' ', $class);
Qiang Xue committed
58
		}
Qiang Xue committed
59
		return Html::beginTag($this->tag, $options);
Qiang Xue committed
60 61 62 63
	}
	
	public function end()
	{
Qiang Xue committed
64 65 66 67 68 69 70 71 72
		return Html::endTag($this->tag);
	}

	public function label($options = null)
	{
		if ($options === null) {
			$options = $this->form->labelOptions;
		}
		return Html::activeLabel($this->model, $this->attribute, $options);
Qiang Xue committed
73 74
	}

Qiang Xue committed
75
	public function error($options = null)
Qiang Xue committed
76
	{
Qiang Xue committed
77
		if ($options === null) {
Qiang Xue committed
78 79 80 81
			$options = $this->form->errorOptions;
		}
		$attribute = Html::getAttributeName($this->attribute);
		$error = $this->model->getFirstError($attribute);
Qiang Xue committed
82 83 84
		if ($error === null) {
			$options['style'] = isset($options['style']) ? rtrim($options['style'], ';') . '; display:none' : 'display:none';
		}
Qiang Xue committed
85 86
		$tag = isset($options['tag']) ? $options['tag'] : 'span';
		unset($options['tag']);
Qiang Xue committed
87 88 89
		return Html::tag($tag, Html::encode($error), $options);
	}

Qiang Xue committed
90
	protected function render($input)
Qiang Xue committed
91
	{
Qiang Xue committed
92 93 94 95 96
		return $this->begin() . "\n" . strtr($this->form->fieldTemplate, array(
			'{input}' => $input,
			'{label}' => $this->label(),
			'{error}' => $this->error(),
		)) . $this->end();
Qiang Xue committed
97 98 99 100 101 102 103 104 105 106 107
	}

	/**
	 * 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())
	{
Qiang Xue committed
108
		return $this->render(Html::activeInput($type, $this->model, $this->attribute, $options));
Qiang Xue committed
109 110 111 112 113 114 115 116 117 118 119 120
	}

	/**
	 * 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())
	{
Qiang Xue committed
121
		return $this->render(Html::activeTextInput($this->model, $this->attribute, $options));
Qiang Xue committed
122 123 124 125 126 127 128 129 130 131 132 133
	}

	/**
	 * 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())
	{
Qiang Xue committed
134
		return $this->render(Html::activeHiddenInput($this->model, $this->attribute, $options));
Qiang Xue committed
135 136 137 138 139 140 141 142 143 144 145 146
	}

	/**
	 * 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())
	{
Qiang Xue committed
147
		return $this->render(Html::activePasswordInput($this->model, $this->attribute, $options));
Qiang Xue committed
148 149 150 151 152 153 154 155 156 157 158 159
	}

	/**
	 * 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())
	{
Qiang Xue committed
160
		return $this->render(Html::activeFileInput($this->model, $this->attribute, $options));
Qiang Xue committed
161 162 163 164 165 166 167 168 169 170 171
	}

	/**
	 * 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())
	{
Qiang Xue committed
172
		return $this->render(Html::activeTextarea($this->model, $this->attribute, $options));
Qiang Xue committed
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
	}

	/**
	 * 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())
	{
Qiang Xue committed
194 195 196 197 198 199 200 201 202 203
		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();
Qiang Xue committed
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224
	}

	/**
	 * 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())
	{
Qiang Xue committed
225 226 227 228 229 230 231 232 233 234
		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();
Qiang Xue committed
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
	}

	/**
	 * 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
	 */
Qiang Xue committed
269
	public function dropDownList($items, $options = array())
Qiang Xue committed
270
	{
Qiang Xue committed
271
		return $this->render(Html::activeDropDownList($this->model, $this->attribute, $items, $options));
Qiang Xue committed
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
	}

	/**
	 * 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())
	{
Qiang Xue committed
311
		return $this->render(Html::activeListBox($this->model, $this->attribute, $items, $options));
Qiang Xue committed
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
	}

	/**
	 * 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);
	}
}