例如,我们在示例视图中有这个ActiveForm
实现:
<?php $form = ActiveForm::begin(); ?>
<?=$form->field($model, 'first_name')->textInput(['maxlength' => true]); ?>
<?=$form->field($model, 'last_name')->textInput(['maxlength' => true]); ?>
<div id="additional-form-fields"></div>
<a href="#" id="load-additional-form-fields">
Load more fields
</a>
<?php ActiveForm::end(); ?>
现在,我想在这个表单中添加更多的ActiveField
/ActiveForm
字段,并将它们放在Ajax的#additional-form-fields
元素中,我会做一个简单的jQuery
回调:
$('#load-additional-form-fields').click(function() {
$.get('/site/additional-fields', {}, function(data) {
$('#additional-form-fields').html( data );
});
});
SiteController
中的动作additional-fields
应该是:
public function actionAdditionalFields() {
$model = new User;
return $this->renderAjax('additional-fields', [
'model' => $model,
// I could pass a 'form' => new ActiveForm, here, but it's a big NO-NO!
]);
}
这工作完美,只有当我不使用任何其他ActiveField
字段在这个动作的视图:
<?=$form->field($model, 'biography')->textInput(['maxlength' => true]); ?>
<?=$form->field($model, 'country')->textInput(['maxlength' => true]); ?>
<?=$form->field($model, 'occupation')->textInput(['maxlength' => true]); ?>
当然,我必须通过或在这个视图中以某种方式建立$form
,但它不是一个选项,使用另一个ActiveForm::begin()
/ActiveForm::end()
在这个视图内的任何地方,因为它将创建另一个<form>
标签,因此,当我注入Ajax响应,我将结束与<form>
内的<form>
…
现在,我的问题如下:既然我想使用ActiveForm
,我如何通过多个请求共享ActiveForm
的实例?
这是可行的/可能的吗?如果是,请帮我弄清楚怎么做?
到目前为止,我试图把$form
在一个会话,但这绝对不工作,而不是一个选项。与此不同的是,我尝试过将参数传递给renderAjax
:
[
'model' => $model,
'form' => new ActiveForm,
]
在这种情况下,我得到以下内容:
- 表单字段被创建为应有的名称和id。 jQuery再次加载(在响应的底部:
- 我没有得到生成的JavaScript验证
<script src="...">
…你懂的)是否有办法共享$form
的实例?
好的,我已经设法做到了这一点,所以我将在这里发布解决方案,我将在Github上打开一个问题-可能在未来的版本中有用。
1。yii2widgetsActiveForm.php
更新我已经添加了以下属性到ActiveForm
类:
/**
* @var boolean whether to echo the form tag or not
*/
public $withFormTag = true;
我已经把run()
方法改成了这个(检查// <-- added
):
public function run()
{
if (!empty($this->_fields)) {
throw new InvalidCallException('Each beginField() should have a matching endField() call.');
}
$content = ob_get_clean();
if($this->withFormTag) { // <-- added
echo Html::beginForm($this->action, $this->method, $this->options);
} // <-- added
echo $content;
if ($this->enableClientScript) {
$id = $this->options['id'];
$options = Json::htmlEncode($this->getClientOptions());
$attributes = Json::htmlEncode($this->attributes);
$view = $this->getView();
ActiveFormAsset::register($view);
$view->registerJs("jQuery('#$id').yiiActiveForm($attributes, $options);");
}
if($this->withFormTag) { // <-- added
echo Html::endForm();
} // <-- added
}
因此,如果我们像这样实例化一个表单:
$form = ActiveForm::begin([
'withFormTag' => false,
]);
它不会echo
一个<form>
标签,但会呈现所有的ActiveField
项目,它将创建各自的JavaScript/jQuery验证器,如果$this->enableClientScript = true;
。
2。更新我的本地视图/文件
在基类中应用先前的修复后,我需要在我的视图中执行以下操作:
<?php $form = ActiveForm::begin([
'withFormTag' => false,
'id' => 'w0',
]); ?>
我必须传递id
参数,因为ActiveForm类的每个下一个实例都由1
递增,我希望我的JavaScript/jQuery验证器应用于父表单,默认情况下从0
开始-> w0
。
这就是成功的秘诀!
这是Github问题:https://github.com/yiisoft/yii2/issues/12973