Last active
February 26, 2018 17:37
-
-
Save lav45/50562bbdd6e7acbcd783a5b36b4e1535 to your computer and use it in GitHub Desktop.
MultipleInput verification through Model
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?= $form->field($model, 'other_software', [ | |
'options' => [ | |
'class' => 'fix-width' | |
] | |
])->widget(MultipleInput::class, [ | |
'columns' => [ | |
[ | |
'name' => 'other_software', | |
'type' => FormBuilder::class, | |
'value' => function ($data) { | |
return $data; | |
}, | |
'options' => [ | |
'form' => $form, | |
'modelClass' => $model->otherSoftwareClass, | |
'fields' => [ | |
'name' => [ | |
'type' => FormBuilder::INPUT_DROPDOWN_LIST, | |
'items' => $anotherSystemList, | |
'options' => ['prompt' => ''], | |
], | |
'units_count' => [ | |
'type' => FormBuilder::INPUT_TEXT, | |
], | |
'transferring_units' => [ | |
'type' => FormBuilder::INPUT_DROPDOWN_LIST, | |
'items' => $model->getTransferringUnitsList(), | |
'options' => ['prompt' => Yii::t('app', '-Select one of the options-')], | |
], | |
'comment' => [ | |
'type' => FormBuilder::INPUT_TEXTAREA, | |
] | |
], | |
], | |
], | |
] | |
]) ?> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class Partner extends ActiveRecord | |
{ | |
/** | |
* @var string | |
*/ | |
public $otherSoftwareClass = OtherSoftwareModel::class; | |
public function rules() | |
{ | |
return [ | |
[['other_software'], 'otherSoftwareValidator'], | |
]; | |
} | |
public function otherSoftwareValidator($attribute) | |
{ | |
$model = new $this->otherSoftwareClass(); | |
$this->dynamicValidator($model, $attribute); | |
} | |
/** | |
* @param Model $model | |
* @param string $attribute | |
* @return array | |
*/ | |
protected function dynamicValidator($model, $attribute) | |
{ | |
$items = $this->$attribute; | |
foreach ($items as $index => $item) { | |
if ($this->isEmpty($item)) { | |
unset($items[$index]); | |
continue; | |
} | |
} | |
// Reset key | |
$items = array_values($items); | |
foreach ($items as $index => $item) { | |
$clone_model = clone $model; | |
$clone_model->setAttributes($item); | |
if ($clone_model->validate() === false) { | |
foreach ($clone_model->getErrors() as $attr => $errors) { | |
$this->addErrors(["{$attribute}[{$index}][{$attr}]" => $errors]); | |
} | |
} | |
foreach ($item as $key => $val) { | |
if ($clone_model->$key != $val) { | |
$items[$index][$key] = $clone_model->$key; | |
} | |
} | |
} | |
$this->$attribute = $items; | |
} | |
/** | |
* @param mixed $items | |
* @return bool | |
*/ | |
protected function isEmpty($items) | |
{ | |
foreach ($items as $value) { | |
if (is_array($value)) { | |
return $this->isEmpty($value); | |
} else { | |
if (!empty($value)) { | |
return false; | |
} | |
} | |
} | |
return true; | |
} | |
public function getTransferringUnitsList() | |
{ | |
return [ | |
1 => Yii::t('app', 'Yes'), | |
2 => Yii::t('app', 'No'), | |
3 => Yii::t('app', 'Planned transfer'), | |
]; | |
} | |
} | |
class OtherSoftwareModel extends Model implements ConfigureFormInterface | |
{ | |
use ConfigureFormTrait; | |
/** | |
* @var integer | |
*/ | |
public $name; | |
/** | |
* @var string | |
*/ | |
public $units_count; | |
/** | |
* @var integer | |
*/ | |
public $transferring_units; | |
/** | |
* @var string | |
*/ | |
public $comment; | |
/** | |
* @return array | |
*/ | |
public function rules() | |
{ | |
return [ | |
[['units_count', 'comment'], 'string'], | |
[['name', 'transferring_units'], 'integer'], | |
]; | |
} | |
/** | |
* @return array | |
*/ | |
public function attributeLabels() | |
{ | |
return [ | |
'name' => 'Software', | |
'units_count' => 'Number of units', | |
'comment' => 'Comment', | |
'transferring_units' => 'Transferring units', | |
]; | |
} | |
} | |
interface ConfigureFormInterface | |
{ | |
public function setFormName($name); | |
} | |
trait ConfigureFormTrait | |
{ | |
private $_formName; | |
public function formName() | |
{ | |
return $this->_formName ? : parent::formName(); | |
} | |
public function setFormName($name) | |
{ | |
$this->_formName = $name; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
use yii\base\Model; | |
use yii\base\Widget; | |
use yii\base\InvalidConfigException; | |
use yii\helpers\ArrayHelper; | |
use yii\widgets\ActiveField; | |
use yii\widgets\InputWidget; | |
class FormBuilder extends Widget | |
{ | |
const INPUT_HIDDEN = 'hiddenInput'; | |
const INPUT_TEXT = 'textInput'; | |
const INPUT_TEXTAREA = 'textarea'; | |
const INPUT_PASSWORD = 'passwordInput'; | |
const INPUT_DROPDOWN_LIST = 'dropdownList'; | |
const INPUT_LIST_BOX = 'listBox'; | |
const INPUT_CHECKBOX = 'checkbox'; | |
const INPUT_RADIO = 'radio'; | |
const INPUT_CHECKBOX_LIST = 'checkboxList'; | |
const INPUT_RADIO_LIST = 'radioList'; | |
const INPUT_FILE = 'fileInput'; | |
const INPUT_HTML5 = 'input'; | |
const INPUT_WIDGET = 'widget'; | |
const INPUT_RAW = 'raw'; | |
/** | |
* @var \yii\widgets\ActiveForm | |
*/ | |
public $form; | |
/** | |
* @var Model|ConfigureFormInterface | |
*/ | |
private $model; | |
/** | |
* @var string | |
*/ | |
public $modelClass; | |
/** | |
* @var array | |
*/ | |
public $fields = []; | |
/** | |
* @var array | |
*/ | |
public $options = []; | |
/** | |
* @var string | |
*/ | |
public $name; | |
/** | |
* @var mixed | |
*/ | |
public $value; | |
/** | |
* @var array | |
*/ | |
public $fieldsOptions = []; | |
public function init() | |
{ | |
parent::init(); | |
$this->model = new $this->modelClass; | |
if (!empty($this->value)) { | |
$this->model->setAttributes($this->value, false); | |
} | |
if ($this->model instanceof ConfigureFormInterface) { | |
$this->model->setFormName($this->name); | |
} | |
} | |
public function run() | |
{ | |
$enableClientValidation = $this->form->enableClientValidation; | |
$this->form->enableClientValidation = false; | |
$content = $this->renderForm($this->model, $this->fields); | |
$this->form->enableClientValidation = $enableClientValidation; | |
return $content; | |
} | |
/** | |
* @param Model $model | |
* @param array $config | |
* | |
* @return null|string | |
*/ | |
public function renderForm(Model $model, array $config) | |
{ | |
$content = null; | |
foreach ($config as $attribute => $options) { | |
$options = array_merge($this->fieldsOptions, $options); | |
$content .= $this->renderField($model, $attribute, $options); | |
} | |
return $content; | |
} | |
/** | |
* @param string $attribute | |
* @param array $settings | |
* @param Model $model | |
* | |
* @return ActiveField | |
* @throws InvalidConfigException | |
*/ | |
public function renderField(Model $model, $attribute, array $settings = []) | |
{ | |
$fieldOptions = ArrayHelper::getValue($settings, 'fieldOptions', []); | |
$field = $this->form->field($model, $attribute, $fieldOptions); | |
if (($label = ArrayHelper::getValue($settings, 'label')) !== null) { | |
$field->label($label, ArrayHelper::getValue($settings, 'labelOptions', [])); | |
} | |
if (($hint = ArrayHelper::getValue($settings, 'hint')) !== null) { | |
$field->hint($hint, ArrayHelper::getValue($settings, 'hintOptions', [])); | |
} | |
$type = ArrayHelper::getValue($settings, 'type', static::INPUT_TEXT); | |
$this->prepareField($field, $type, $settings); | |
return $field; | |
} | |
/** | |
* @param ActiveField $field | |
* @param $type | |
* @param array $settings | |
* @throws InvalidConfigException | |
*/ | |
protected function prepareField($field, $type, array $settings) | |
{ | |
$options = ArrayHelper::getValue($settings, 'options', []); | |
switch ($type) { | |
case static::INPUT_HIDDEN: | |
case static::INPUT_TEXT: | |
case static::INPUT_TEXTAREA: | |
case static::INPUT_PASSWORD: | |
case static::INPUT_FILE: | |
$field->$type($options); | |
break; | |
case static::INPUT_DROPDOWN_LIST: | |
case static::INPUT_LIST_BOX: | |
case static::INPUT_CHECKBOX_LIST: | |
case static::INPUT_RADIO_LIST: | |
$items = ArrayHelper::getValue($settings, 'items', []); | |
$field->$type($items, $options); | |
break; | |
case static::INPUT_CHECKBOX: | |
case static::INPUT_RADIO: | |
$enclosedByLabel = ArrayHelper::getValue($settings, 'enclosedByLabel', true); | |
$field->$type($options, $enclosedByLabel); | |
break; | |
case static::INPUT_HTML5: | |
$html5type = ArrayHelper::getValue($settings, 'html5type', 'text'); | |
$field->$type($html5type, $options); | |
break; | |
case static::INPUT_WIDGET: | |
$widgetClass = $this->getWidgetClass($settings); | |
$field->$type($widgetClass, $options); | |
break; | |
case static::INPUT_RAW: | |
$field->parts['{input}'] = $this->getValue($settings); | |
break; | |
default: | |
throw new InvalidConfigException("Invalid input type '{$type}' configured for the attribute."); | |
} | |
} | |
/** | |
* @param array $settings | |
* @return mixed | |
* @throws InvalidConfigException | |
*/ | |
protected function getWidgetClass(array $settings) | |
{ | |
$widgetClass = ArrayHelper::getValue($settings, 'widgetClass'); | |
if (empty($widgetClass) && !$widgetClass instanceof InputWidget) { | |
throw new InvalidConfigException("A valid 'widgetClass' must be setup and extend from '\\yii\\widgets\\InputWidget'."); | |
} | |
return $widgetClass; | |
} | |
/** | |
* @param array $settings | |
* @return mixed|string | |
*/ | |
protected function getValue(array $settings) | |
{ | |
$value = ArrayHelper::getValue($settings, 'value', ''); | |
if (is_callable($value)) { | |
return call_user_func($value); | |
} elseif (!is_string($value)) { | |
return ''; | |
} | |
return $value; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.fix-width > [class*="col-"] { | |
width: 100%; | |
padding-right: 0; | |
padding-left: 0; | |
} | |
.fix-width > div > .multiple-input { | |
margin-right: -15px; | |
margin-left: -15px; | |
} | |
.fix-width > div > .multiple-input > .multiple-input-list > tbody > .multiple-input-list__item > .list-cell__button { | |
position: absolute; | |
right: 20px; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment