You are viewing revision #7 of this wiki article.
This is the latest version of this article.
You may want to see the changes made in this revision.
With Yii you can use one CActiveForm for collecting data for two or more models with ajax validation and client validation.
According this article you can also create a form with ajax validation for both models.
You have two models $a and $b.
create.php
<?php $form = $this->beginWidget('CActiveForm', array(
'id'=>'user-form',
'enableAjaxValidation'=>true,
)); ?>
<?php echo $form->errorSummary(array($a,$b)); ?>
<div class="row">
<?php echo $form->labelEx($a,'firstName'); ?>
<?php echo $form->textField($a,'firstName'); ?>
<?php echo $form->error($a,'firstName'); ?>
</div>
<div class="row">
<?php echo $form->labelEx($b,'lastName'); ?>
<?php echo $form->textField($b,'lastName'); ?>
<?php echo $form->error($b,'lastName'); ?>
</div>
<?php $this->endWidget(); ?>
controller:
public function actionCreate()
{
$a=new User;
$b=new Info;
$this->performAjaxValidation(array($a,$b));
if(isset($_POST['User'],$_POST['Info']))
{
// populate input data to $a and $b
$a->attributes=$_POST['User'];
$b->attributes=$_POST['Info'];
// validate BOTH $a and $b
$valid=$a->validate();
$valid=$b->validate() && $valid;
if($valid)
{
// use false parameter to disable validation
$a->save(false);
$b->save(false);
$this->redirect('index');
}
}
$this->render('create',array('a'=>$a,'b'=>$b));
}
protected function performAjaxValidation($models)
{
if(isset($_POST['ajax']) && $_POST['ajax']==='user-form')
{
echo CActiveForm::validate($models);
Yii::app()->end();
}
}
Thats all, now you have form with 2 models and ajaxValidation.
error summary
I think this:
echo $form->errorSummary($model);
should be changed to something like:
echo $form->errorSummary($a); echo $form->errorSummary($b);
or the validation will not work...
great article , learn some new skills!
i never known that isset() function can accepts more than one parameters util seen this article :D; and found that : CActiveForm::validate($models); the validate function can give many models ; well done!
comment
@rusalex, you should probably use a transaction, otherwise if one model->save() fails, you might have some dangling models
@redguy, did you test it? errorSummary can accept an array of models
also note that isset() does and AND, not an OR
@el chief
@el chief: now is also ok. Earlier there was reference to not declared variable: $model.
@el chief
yes, it's a simple ideal way to save data. you need to write your own validation process.
saving not good
if($a->save() && $b->save())
is not good because if for any reason ajax validation pass and then the validation at $b-save() fails the $a record will be saved.
Take a look at the original article for validating / saving the data.
Fixed
@mdomba, fixed.
FK has a temporary value.
I modified that FK has a temp value in order to pass validity check.
It will rollback as deleting a record of the referenced table if fails to save a record of the referencing table.
It seems to work fine.
$user=new User('register'); $profile=new UserProfile('create'); if(isset($_POST['User'])&&isset($_POST['UserProfile'])) { $user->attributes=$_POST['User']; // FK user_id has a temporary value as zero to validate $profile->user_id=0; $profile->attributes=$_POST['UserProfile']; if($user->validate()&&$profile->validate()) { if($user->save()) { // FK now has a proper value. $profile->user_id=$user->id; if($profile->save()) $this->redirect(array('site/index')); else // rollback if fails to save profile $user->delete(); } } }
Gratitude
Thank you SO MUCH.
If you have any questions, please ask in the forum instead.
Signup or Login in order to comment.