Yii 1.1: How to use single form to collect data for two or more models (CActiveForm and Ajax Validation edition)

34 followers

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.

Links ΒΆ

Total 9 comments

#15112 report it
theHunter at 2013/10/08 11:52am
Gratitude

Thank you SO MUCH.

#9572 report it
jonghwa at 2012/08/23 09:24pm
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();
                                }
                        }
                }
#5410 report it
resurtm at 2011/10/10 07:59am
Fixed

@mdomba, fixed.

#5409 report it
Maurizio Domba Cerin at 2011/10/10 07:50am
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.

#4582 report it
RusAlex at 2011/07/22 02:02am
@el chief

yes, it's a simple ideal way to save data. you need to write your own validation process.

#4581 report it
redguy at 2011/07/22 01:22am
@el chief

@el chief: now is also ok. Earlier there was reference to not declared variable: $model.

#4578 report it
el chief at 2011/07/21 04:09pm
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

#4559 report it
yiqing95 at 2011/07/20 01:27pm
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!

#4554 report it
redguy at 2011/07/20 09:14am
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...

Leave a comment

Please to leave your comment.

Write new article