Nested forms

I already tried the new form builder but had no luck displaying validation errors. So I tried it the "old fanshioned way" - but also had no luck. Maybe you can help me?

For subscription I have a simple form:

[list=1]

[*]Enter email address (Text input field)

[*]Choose gender (2 Radio buttons)

[*]Choose profile type (OptionList with predefined profiles)

[/list]

I want to validate the input and then insert the data into 3 tables (Account, AccountProfile and Email).This is, because one user can have only one account, but muliple profiles and email addresses.

So my 3 models look like this (simplified):

[Account]

  • gender_id (related to Gender)

[AccountProfile]

  • account_id (related to Account)

  • profile_id (related to Profile)

[Email]

  • email_address

  • account_id (related to Account)

So how can I create a form (and later validate it)?

I cannot see a problem.

Just create a simple CFormModel, validate your Form, then create/update your tables




if ($form->validate()) {

    $account = new Account;

    $account->gender = $form->gender;

    $account->save();


    $email = new Email;

    $email->address = $form->emailAdress;

    $email->save();


    ....

}



Maybe I’m wrong, but this way I have to define the validation rules for every subscription field twice, right?

Once in the form itself, and once more in the affected models (Account, Email, Gender, Profile, AccountEmail and AccountProfile).

If for example the email address has to be unique (which actually is the case), I can’t check this using the CFormModel. So the first time this error appears, would be in the last line of your example, after a new account is already created and I’m failing to save the email address.

I know: This could be solved opening a transaction and executing a rollback. But to display the correct error message for the email field, I’d also have to manually assign the error provided by the “Email”-model to the related field, right?

you could use the account model to collect all data and save to other models in Account::afterSave()

i did something similar.

the simple way:




public function rules()

{

    return array(

        array('email', 'checkEmail'),

    );

}

 

public function checkEmail($attribute,$params)

{

    if(!$this->hasErrors()) {

        $address = Email::model()->find('address = ?', array($this->address));

        if ($address) {

            $this->addError('address', 'Email has already been taken');

        }

    }

}



OK, thank you. It works - although these are all work arounds :)

I hoped it would be possible to define a scenario "subscribe" in every model and then build a form where the HTML would look like this:




<input type="radio" name="Subscribe[Account][gender_id]" value="m" /> Male

<input type="radio" name="Subscribe[Account][gender_id]" value="f" /> Female


<input type="text" name="Subscribe[Email][email_address]" />


<select name="Subscribe[Profile][id]">

    <option value="1">Webmaster</option>

    <option value="2">System administrator</option>

</select>



The validation sth like this




    $form->attributes = Yii::app()->request->getParam('Subscribe');


    if ($form->validate()) ...



It would check if

  • all fields required for the subscribe scenario are filled out

  • gender_id is a valid id from the genders table (f or m)

  • profile_id is a valid id and activated in the profiles table

  • email_address is not in the emails table and is a valid email address

I know now how to do this manually, but this simple scenario needs me to write 3 custom validation functions doing the same what the rules in the models already do.

Every time I change something in a model I have to remember that there’s a bunch of custom validation functions I also have to adapt.

Thank you anyway. If I found what I was looking for I’ll update this thread … maybe I’ll give the form builder another chance ;)

Hi Every body !!

i have nested forms like the following

[indent]return array(

‘activeForm’ => array(

‘class’ => ‘CActiveForm’,

‘enableAjaxValidation’ => true,

‘enableClientValidation’ => false,

‘clientOptions’ => array(

‘validateOnSubmit’=>true,

‘validateOnChange’=>false,

‘validateOnType’=>false,

),

‘id’ => ‘lead-form’,

),

‘elements’=>array(

‘contact’=>array(

‘type’=>‘form’,

‘elements’=>array(

‘first_name’=>array(

‘type’=>‘text’,

)

),

),

‘lead’=>array(

‘type’=>‘form’,

‘elements’=>array(

‘primary_skills’=>array(

‘type’=>‘textarea’,

),

),

),

),

‘buttons’=>array(

‘save-lead’=>array(

‘type’=>‘submit’,

‘label’=>‘Create’,

),

)

);

[/indent]

my view page is

[indent] echo $form->renderBegin();

echo $form[‘lead’];

echo $form->buttons[‘save-lead’];

echo $form->renderEnd();

[/indent]

it works fine for ajax validation.

but when i render the form two times on same view page then only the first one is ajax validated but not the 2nd one…

my 2nd scenario is like this

[indent] echo $form->renderBegin();

echo $form[‘lead’];

echo $form->buttons[‘save-lead’];

echo $form->renderEnd();

echo $form->renderBegin();

echo $form[‘contact’];

echo $form[‘lead’];

echo $form->buttons[‘save-lead’];

echo $form->renderEnd();

[/indent]

so in this case 2nd render() is not ajax validated…

anyone can help plzzzz ??????