【发布时间】:2014-01-06 22:01:21
【问题描述】:
我基本上是在尝试使用 Yii 中的 CActiveForm 类创建一个多步骤表单。我的想法是我想使用内置功能以最简单的方式实现这一目标。我的要求如下:
- 多步骤一页表单(使用通过 jQuery 显示/隐藏的 DIV)
- 每个步骤的 AJAX 验证(仅验证特定于步骤的属性)
- 必须使用
validateOnChange()和validateOnSubmit()方法进行验证
这是我迄今为止开发的一个半有效的解决方案:
查看:
<div class="form">
<?php $form = $this->beginWidget('CActiveForm', array(
'id'=>'listing-form',
'enableClientValidation'=>false,
'enableAjaxValidation'=>true,
'clientOptions'=>array(
'validateOnChange'=>true,
'validateOnSubmit'=>true,
'afterValidate'=>'js:validateListing',
),
)); ?>
<?php echo $form->errorSummary($model); ?>
<div class="step" id="step-1">
// model input fields
<?php echo CHtml::submitButton('Next Step', array('name'=>'step1')); ?>
</div>
<div class="step" id="step-2" style="display: none;">
// model input fields
<?php echo CHtml::submitButton('Next Step', array('name'=>'step2')); ?>
</div>
<div class="step" id="step-3" style="display: none;">
// model input fields
<?php echo CHtml::submitButton('Submit', array('name'=>'step3')); ?>
</div>
<?php $this->endWidget(); ?>
</div>
JavaScript:
function validateListing(form, data, hasError)
{
if(hasError)
{
// display JS flash message
}
else
{
if($('#step-1').css('display') != 'none')
{
$('#step-1').hide();
$('#step-2').show();
}
else if($('#step-2').css('display') != 'none')
{
$('#step-2').hide();
$('#step-3').show();
}
else if($('#step-3').css('display') != 'none')
{
return true; // trigger default form submit
}
}
}
控制器:
public function actionCreate()
{
$model = new Listing;
// step 1 ajax validation
if(isset($_POST['step1']))
{
$attributes = array('name', 'address1', 'etc');
$this->performAjaxValidation($model, $attributes);
}
// step 2 ajax validation
if(isset($_POST['step2']))
{
$attributes = array('category', 'type', 'etc');
$this->performAjaxValidation($model, $attributes);
}
// step 3 ajax validation
if(isset($_POST['step3']))
{
$attributes = array('details', 'source', 'etc');
$this->performAjaxValidation($model, $attributes);
}
// process regular POST
if(isset($_POST['Listing']))
{
$model->attributes = $_POST['Listing'];
if($model->validate()) // validate all attributes again to be sure
{
// perform save actions, redirect, etc
}
}
$this->render('create', array(
'model'=>$model,
));
}
protected function performAjaxValidation($model, $attributes=null)
{
if(isset($_POST['ajax']) && $_POST['ajax']==='listing-form')
{
echo CActiveForm::validate($model, $attributes);
Yii::app()->end();
}
}
总结一下。基本上我所拥有的是一个带有 3 个提交按钮的表单(每个步骤一个)。在我的控制器中,我检查按下了哪个提交按钮,并对特定于该步骤的属性运行 AJAX 验证。
我使用自定义afterValidate() 函数在提交时显示/隐藏步骤。在第 3 步,触发了默认的表单提交,它将所有表单属性发布到控制器。
这很好用,但它不适用于validateOnChange()(因为没有发布提交按钮)。另外我想知道这是否实际上是最好的方法,或者是否有人知道更好的方法?
谢谢。
【问题讨论】:
-
如何在模型中使用场景?请更新您的代码
标签: yii