An initial implementation is checked in. Using the blog demo as an example, the create action and view can be rewritten like the following:
actionCreate:
<?php
public function actionCreate()
{
$form=new PostForm($this, new Post);
if($form->submitted())
{
if($form->clicked('preview'))
$form->model->validate();
else if($form->clicked('create') && $form->model->save())
$this->redirect(array('show','id'=>$form->model->id));
}
$this->render('create',array('form'=>$form,'model'=>$form->model));
}
create.php
<?php
<h2>Create New Post</h2>
<?php echo $form->render(); ?>
<?php if($form->clicked('preview') && !$model->hasErrors()): ?>
...display preview here...
PostForm:
<?php
class PostForm extends CForm
{
public function init()
{
$spec=array(
'elements'=>array(
'title'=>array(
'type'=>'text',
'size'=>65,
'maxlength'=>128,
),
'content'=>array(
'type'=>'textarea',
'rows'=>20,
'cols'=>50,
),
'tags'=>array(
'type'=>'text',
'size'=>65,
),
'status'=>array(
'type'=>'dropdownlist',
'items'=>Post::model()->statusOptions,
),
),
'buttons'=>array(
'update'=>array(
'type'=>'submit',
'label'=>'Save',
'on'=>'update'
),
'create'=>array(
'type'=>'submit',
'label'=>'Create',
'on'=>'insert',
),
'preview'=>array(
'type'=>'submit',
'label'=>'Preview',
),
),
);
$this->configure($spec);
}
}
Features:
-
Supports sub-forms and multiple models
-
Supports widgets and plain strings to be embedded in the form
-
Arbitrary manipulation of the whole form hierarchy, using the familiar array syntax. For example
<?php
$form['title']->size=100;
Pros:
-
The _form.php partial view is eliminated, which is replaced by the single call $form->render().
-
Code relevant to input configuration is separated from the rest of the presentational code.
-
By customizing the base form's render() method, we can change the appearance of the forms in an application consistently and easily.
Cons:
-
The form rendering logic is relatively rigid since it treats all kinds of forms the same.
-
It introduces an additional layer of abstraction, which means additional learning curve.