How to use form builder

NOTE: this feature may still be changed before we formally release 1.1.

A snippet for creating a login form is as follows:




// --- login action ---


// the configuration describing the form

// this is an array of name-value pairs

// used to initialize the properties of CForm

// Please check CForm's API for how to configure

// 'elements' and 'buttons'

$config=array(

    'elements'=>array(

        'username'=>array(

            'type'=>'text',

        ),

        'password'=>array(

            'type'=>'password',

        ),

        'rememberMe'=>array(

            'type'=>'checkbox',

        )

    ),

    'buttons'=>array(

        'login'=>array(

            'type'=>'submit',

            'label'=>'Login',

        ),

    ),

);


// generate the form using the above config

// and the LoginForm model

$form=new CForm($config, new LoginForm);


// check if the form is submitted and the inputs are valid

if($form->submitted() && $form->validate())

    $this->redirect(array('site/index'));


$this->render('login', array('form'=>$form));




// --- login view ---

<h1>Login</h1>


<?php echo $form; ?>



In the above, the form configuration may be stored in a separate file or be returned by the model class.

Themain benefit of using form builder is the separation of logic(elements, buttons) and presentation (how to render thoseelements/buttons).

As a result, we can extend CForm or use differentviews to render a form object so that the same set of elements/buttonscan be rendered differently and in a consistent way across the wholeapplication.

wow! very nice feature

its very easy to build form templates with this

i appreciate the idea

Please can you give an example of the configuration of a form with subforms? This is still eluding me…

what are subforms?

It doesn’t work:( Form is building, but controller is not responding on $form->submitted(). Old way with isset($_POST[‘LoginForm’]) works fine.

Looked in the source code of CForm and found there, what submitted() needs an argument, which declare name of ‘submit’ button. So, for:


'buttons'=>array(

        'login'=>array(

            'type'=>'submit',

            'label'=>'Login',

        ),

    ),



I need to set name of submit button in submitted() function like this:


$form->submitted('login')

I did some testing with a form contatining two subforms. All of the forms has a couple of buttons.

Results using if $form->submitted(‘name_of_button’):

  1. buttons in main form, nothing posted from the browser (invalid use?).

  2. buttons in first subform works, seemingly because uniqueId for both main form and first subform are posted.

  3. buttons in second subform does not work, only the subforms uniqueIs is posted.

(Firefox 3.5.5)

Edit:

Tried to specify the subforms button but haven’t figured out how to access the subform config.

/Tommy

How do you add a preview ability using the form builder? I can’t work out how to get the values submitted in the view. They all seem to be under “_model”:“CForm”:private.

Found it:


$form->model

I just added a tutorial on using the former builder: http://www.yiiframework.com/doc/guide/form.builder

Please let me know if you find any errors in the tutorial examples and the form builder code. Thanks!

I created a simple form like this

controller code:




	public function actionLogin()

	{

		$model = new LoginForm;

		$form  = new CForm('application.views.forms.LoginForm', $model);

		if($form->submitted() && $form->validate())

		{

			$this->redirect(Yii::app()->user->returnUrl);

		}else{

			// display the login form

			$this->render('login',array('form'=>$form));

		}		

	}



form definition:




return array(

	'title'=>'Please provide your login credential',

	'elements'=>array(

		'username'=>array(

			'type'=>'text',

		),

		'password'=>array(

			'type'=>'password',

		),

		'rememberMe'=>array(

			'type'=>'checkbox',

		),

	),

	'buttons'=>array(

		'login'=>array(

			'type'=>'submit',

			'label'=>'Login',

		),

	),

);



and i use


<?php echo $form; ?>

in my view file.

When i click the submit button the form, the condition in the if selection evaluates to boolean false.

when i change the code


$form->submitted()

to


$form->submitted('login')

it works fine.

Is that the desired behaviour or is it an error?

upon inspecting CForm::submitted(), i realized it method accepts the name of the button as a parameter




        public function submitted($buttonName='submit',$loadData=true)

        {

                $ret=$this->clicked($this->getUniqueId()) && $this->clicked($buttonName);

                if($ret && $loadData)

                        $this->loadData();

                return $ret;

        }



which defaults to ‘submit’ if not specified.

in the example you have in the documentation you should either pass ‘login’ to the CForm::submitted() or change the button from ‘login’ to submit in the form defenition.

Thanks. Fixed.

Converting 1.0 form to 1.1 I get an error:

Fatal error: Call to a member function isAttributeSafe() on a non-object in G:\home\www\framework1\web\form\CFormInputElement.php on line 216

Also how to add scenario with the form builder would be great

What do you mean converting from 1.0 to 1.1? There is no form builder in 1.0.

For the error you described, are you sure your CForm is associated with a model object?

Scenario is set in the model object as a property.

i got the same error he mentioned when i create an instance of CForm without passing the model as a second parameter.

You need a model as the input elements require it.

I realised, i was just following the example in the documentation for registration.

Thank you that was dumb me

How can I fill the values of form???

when I try




$model = new Post;

$model->findByPk(2);

$form=new CForm($config, $model);



form is not filled.

how about $model = Post::model()->findByPk(2); ?