YII2 添加 whenClient 到动态表单
YII2 Adding whenClient to a dynamic form
我用过dynamic form widget。表单字段如下图所示。如您所见,有一个名为取消的复选框。我想要的是,如果单击 cancel
复选框,它将只需要支票号码,其余的可以留空。在不使用动态表单的情况下,我可以使用 when
和 whenClient
验证器轻松实现这一点,因为我可以获得复选框的准确 name
。
这里的问题是动态表单会为复选框生成这种 name
系列...
TblDvBub[0][is_cancelled][]
TblDvBub[1][is_cancelled][]
TblDvBub[2][is_cancelled][]
我认为您可以使用 'attribute.name' 从 'whenClient' => 'function(attribute, value){}' 参数中提取 is_cancelled 复选框的名称。 console.log 那 'attribute' - 必须有一个带有 'name' 属性 的对象 - 你可能会得到当前 TblDvBub 的编号(使用正则表达式)。
顺便问一下,为什么要使用多个 is_cancelled[] 字段 - 它不是已经属于特定的 TblDvBub 子数组了吗?
1) 在表单中,必须重写fieldClass
<?php $form = ActiveForm::begin([
'fieldClass' => 'backend\widgets\ActiveField'
]); ?>
2) 覆盖方法
<?php
class ActiveField extends \yii\widgets\ActiveField
{
protected function getClientOptions()
{
$attribute = Html::getAttributeName($this->attribute);
if (!in_array($attribute, $this->model->activeAttributes(), true)) {
return [];
}
$enableClientValidation = $this->enableClientValidation || $this->enableClientValidation === null && $this->form->enableClientValidation;
$enableAjaxValidation = $this->enableAjaxValidation || $this->enableAjaxValidation === null && $this->form->enableAjaxValidation;
if ($enableClientValidation) {
$validators = [];
foreach ($this->model->getActiveValidators($attribute) as $validator) {
/* @var $validator \yii\validators\Validator */
$js = $validator->clientValidateAttribute($this->model, $attribute, $this->form->getView());
if ($validator->enableClientValidation && $js != '') {
if ($validator->whenClient !== null) {
$js = "if (({$validator->whenClient})(attribute, value, '{$this->form->id}')) { $js }";
}
$validators[] = $js;
}
}
}
if (!$enableAjaxValidation && (!$enableClientValidation || empty($validators))) {
return [];
}
$options = [];
$inputID = $this->getInputId();
$options['id'] = $inputID;
$options['name'] = $this->attribute;
$options['container'] = isset($this->selectors['container']) ? $this->selectors['container'] : ".field-$inputID";
$options['input'] = isset($this->selectors['input']) ? $this->selectors['input'] : "#$inputID";
if (isset($this->selectors['error'])) {
$options['error'] = $this->selectors['error'];
} elseif (isset($this->errorOptions['class'])) {
$options['error'] = '.' . implode('.', preg_split('/\s+/', $this->errorOptions['class'], -1, PREG_SPLIT_NO_EMPTY));
} else {
$options['error'] = isset($this->errorOptions['tag']) ? $this->errorOptions['tag'] : 'span';
}
$options['encodeError'] = !isset($this->errorOptions['encode']) || $this->errorOptions['encode'];
if ($enableAjaxValidation) {
$options['enableAjaxValidation'] = true;
}
foreach (['validateOnChange', 'validateOnBlur', 'validateOnType', 'validationDelay'] as $name) {
$options[$name] = $this->$name === null ? $this->form->$name : $this->$name;
}
if (!empty($validators)) {
$options['validate'] = new JsExpression("function (attribute, value, messages, deferred, $form) {" . implode('', $validators) . '}');
}
// only get the options that are different from the default ones (set in yii.activeForm.js)
return array_diff_assoc($options, [
'validateOnChange' => true,
'validateOnBlur' => true,
'validateOnType' => false,
'validationDelay' => 500,
'encodeError' => true,
'error' => '.help-block',
]);
}
}
?>
3) 验证可以使用
<?php
'whenClient' => "function(attribute, value, form) {
$("form# " + form + " > attribute")
}"
?>
我用过dynamic form widget。表单字段如下图所示。如您所见,有一个名为取消的复选框。我想要的是,如果单击 cancel
复选框,它将只需要支票号码,其余的可以留空。在不使用动态表单的情况下,我可以使用 when
和 whenClient
验证器轻松实现这一点,因为我可以获得复选框的准确 name
。
这里的问题是动态表单会为复选框生成这种 name
系列...
TblDvBub[0][is_cancelled][]
TblDvBub[1][is_cancelled][]
TblDvBub[2][is_cancelled][]
我认为您可以使用 'attribute.name' 从 'whenClient' => 'function(attribute, value){}' 参数中提取 is_cancelled 复选框的名称。 console.log 那 'attribute' - 必须有一个带有 'name' 属性 的对象 - 你可能会得到当前 TblDvBub 的编号(使用正则表达式)。 顺便问一下,为什么要使用多个 is_cancelled[] 字段 - 它不是已经属于特定的 TblDvBub 子数组了吗?
1) 在表单中,必须重写fieldClass
<?php $form = ActiveForm::begin([
'fieldClass' => 'backend\widgets\ActiveField'
]); ?>
2) 覆盖方法
<?php
class ActiveField extends \yii\widgets\ActiveField
{
protected function getClientOptions()
{
$attribute = Html::getAttributeName($this->attribute);
if (!in_array($attribute, $this->model->activeAttributes(), true)) {
return [];
}
$enableClientValidation = $this->enableClientValidation || $this->enableClientValidation === null && $this->form->enableClientValidation;
$enableAjaxValidation = $this->enableAjaxValidation || $this->enableAjaxValidation === null && $this->form->enableAjaxValidation;
if ($enableClientValidation) {
$validators = [];
foreach ($this->model->getActiveValidators($attribute) as $validator) {
/* @var $validator \yii\validators\Validator */
$js = $validator->clientValidateAttribute($this->model, $attribute, $this->form->getView());
if ($validator->enableClientValidation && $js != '') {
if ($validator->whenClient !== null) {
$js = "if (({$validator->whenClient})(attribute, value, '{$this->form->id}')) { $js }";
}
$validators[] = $js;
}
}
}
if (!$enableAjaxValidation && (!$enableClientValidation || empty($validators))) {
return [];
}
$options = [];
$inputID = $this->getInputId();
$options['id'] = $inputID;
$options['name'] = $this->attribute;
$options['container'] = isset($this->selectors['container']) ? $this->selectors['container'] : ".field-$inputID";
$options['input'] = isset($this->selectors['input']) ? $this->selectors['input'] : "#$inputID";
if (isset($this->selectors['error'])) {
$options['error'] = $this->selectors['error'];
} elseif (isset($this->errorOptions['class'])) {
$options['error'] = '.' . implode('.', preg_split('/\s+/', $this->errorOptions['class'], -1, PREG_SPLIT_NO_EMPTY));
} else {
$options['error'] = isset($this->errorOptions['tag']) ? $this->errorOptions['tag'] : 'span';
}
$options['encodeError'] = !isset($this->errorOptions['encode']) || $this->errorOptions['encode'];
if ($enableAjaxValidation) {
$options['enableAjaxValidation'] = true;
}
foreach (['validateOnChange', 'validateOnBlur', 'validateOnType', 'validationDelay'] as $name) {
$options[$name] = $this->$name === null ? $this->form->$name : $this->$name;
}
if (!empty($validators)) {
$options['validate'] = new JsExpression("function (attribute, value, messages, deferred, $form) {" . implode('', $validators) . '}');
}
// only get the options that are different from the default ones (set in yii.activeForm.js)
return array_diff_assoc($options, [
'validateOnChange' => true,
'validateOnBlur' => true,
'validateOnType' => false,
'validationDelay' => 500,
'encodeError' => true,
'error' => '.help-block',
]);
}
}
?>
3) 验证可以使用
<?php
'whenClient' => "function(attribute, value, form) {
$("form# " + form + " > attribute")
}"
?>