Yii Framework Forum: CForm - Yii Framework Forum

Jump to content

  • (3 Pages)
  • +
  • 1
  • 2
  • 3
  • You cannot start a new topic
  • You cannot reply to this topic

CForm Rate Topic: -----

#1 User is offline   qiang 

  • Yii Project Lead
  • Yii
  • Group: Yii Dev Team
  • Posts: 5,874
  • Joined: 04-October 08
  • Location:DC, USA

Posted 19 June 2009 - 11:22 AM

Building HTML form is often time-consuming and repetitive. Currently, we usually call CHtml methods to generate labels and input fields, and embed them in HTML code. If we need to different a new form, we would repeat the whole process again. The proposal for CForm is to alleviate this problem.

The main idea is that we use a CForm object to represent the collection of the input fields. The CForm object is backed by a model object which is responsible to perform data validation and other biz logic. The CForm object itself doesn't have any logic and only serves as a container of the input field specifications. For example, a CForm object could be built as:

$model=new LoginFormModel;
$form=new CForm($model, 'path/to/specFile');

where the spec file looks like

return array(
'username'=>array(
'label'=>'Username', // optional, would be determined by model
'required'=>true,    // optional, would be determined by model
'type'=>'CTextField',// optional, CTextField
'maxlength'=>80,
),
'password'=>array(
'label'=>'Password', // optional, would be determined by model
'required'=>true,    // optional, would be determined by model
'type'=>'CPasswordField',
),
);


Because CForm is just a container, in order to render the form, we need to a view (template). The simplest view template could look like the following:

$form->begin();
foreach($form->elements as $element)
{
echo $element->label."<br/>".$element->render()."<br/>";
echo $element->error;
}
$form->end();


You may think such rendering is too rigid. If so, you may write another view template, or simplest render the form element one by one in a very complex form layout.

So what are the benefits of this additional abstraction? First, the same CForm object can be rendered using different view templates, which means reusing the form. Second, the same view template can be used to render different CForm objects, which means reusing the view template. Third, when developing a form, developers can focus on writing the form spec while designers focus on views or view templates.

The following is the typical code needed in a controller action:

$model=new LoginFormModel;
$form=new CForm($model, 'path/to/spec');
if($form->submitted())
{
$form->loadData();
if($model->validate())
$this->redirect(...);
}
$this->render('create', array('form'=>$form, 'model'=>$model));


The new code doesn't look any more complex than our existing one. It is actually a bit more readable.

There are still some problems regarding this form design:
1. How to represent a form involving several models?
2. How to deal with tabular data input?
3. How to group form elements?

Your questions and suggestions are welcome!


0

#2 User is offline   Darmen 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 68
  • Joined: 28-February 09
  • Location:Astana, Kazakhstan

Posted 19 June 2009 - 11:42 AM

Good idea, Qiang!

Quote

1. How to represent a form involving several models?

Do you mean other models related to current one? Maybe, something like embedded forms. We can see them in Symfony, for example.

Quote

3. How to group form elements?

Maybe something like this:
return array('personal_info_group', 'Personal Info', array(... elements here...));

0

#3 User is offline   PoL 

  • Advanced Member
  • PipPipPip
  • Yii
  • Group: Members
  • Posts: 506
  • Joined: 05-November 08
  • Location:Buenos Aires, Argentina

Posted 19 June 2009 - 12:14 PM

I think:
CForm can have properties like action, etc.
For 1. may be,
$form=new CForm(array('model1'=>$model1, 'model2'=>$model2), 'path/to/specFile');
or may be something like:
$form=new CForm(
  array(
      'model1' => array('model'=>$model1, 'spec'=>'path/to/specFile1'),
      'model2' => array('model'=>$model1, 'spec'=>'path/to/specFile2'),
);

Etc...
2. Thinking.... no idea yet...
3. may be defining the group in the specFile:

return array(
'group1'=>array(
'username'=>array(
'label'=>'Username', // optional, would be determined by model
'required'=>true,    // optional, would be determined by model
'type'=>'CTextField',// optional, CTextField
'maxlength'=>80,
),
'password'=>array(
'label'=>'Password', // optional, would be determined by model
'required'=>true,    // optional, would be determined by model
'type'=>'CPasswordField',
),
),
'group2'=>array('someField1'=>..., etc),
);
0

#4 User is offline   Ismael 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 163
  • Joined: 02-June 09
  • Location:Brazil

Posted 19 June 2009 - 04:06 PM

I have experience with Zend Framework and I can say is Yii shall get inspiration from it.

1. How to represent a form involving several models?

Like form and subforms: http://framework.zen...form.forms.html

Take a look how is simple in zend framework:
This is FORM (base)
<?php

require SITE_FORMS . 'SubFormulario_Inscreva.php';
require SITE_FORMS . 'SubFormulario_MaisPessoas.php';

class Formulario_Inscreva extends Zend_Form
{
public function init()
{
$this->setAction('')
    ->setMethod('post');

$inscreva    = new SubFormulario_Inscreva();
$maispessoas = new SubFormulario_MaisPessoas();

$this->addSubForm($inscreva  , 'inscreva');
$this->addSubForm($maispessoas, 'maispessoas');

$submit = new Zend_Form_Element_Submit('submit');
$submit->setLabel('Enviar')
->setDecorators(array(
array(
'decorator' => 'ViewHelper',
'options' => array('helper' => 'formSubmit')),
array(
'decorator' => array('td' => 'HtmlTag'),
'options' => array('tag' => 'td', 'colspan' => 2)),
array(
'decorator' => array('tr' => 'HtmlTag'),
'options' => array('tag' => 'tr')),
array(
'decorator' => array('table' => 'HtmlTag'),
'options' => array('tag' => 'table')),
    ));

$this->setDecorators(
array('FormElements'
  , array('Form')
)
);

        $this->addElements(
array($submit
        )
    );

}
}


This is one of sub-form attached in base form
<?php

/**
*  Nome
    *  Empresa
    *  CPF/CNPJ
    *  Endereço
    *  Bairro
    *  Cidade
    *  Estado
    *  Telefone
    *  E-mail
    *  Site
    *  Forma de pagamento
    *  Observação
    *
    *  Sub-Formulário
    *      Nome Completo
    *      Nome para Crachá
    *      E-mail
*/

require SITE_FORMS . 'Form_Element_Radio_Formapagemento.php';
require SITE_FORMS . 'Form_Element_Select_Estado.php';
require SITE_FORMS . 'Form_Element_Text_Bairro.php';
require SITE_FORMS . 'Form_Element_Text_CPFCNPJ.php';
require SITE_FORMS . 'Form_Element_Text_Cidade.php';
require SITE_FORMS . 'Form_Element_Text_Email.php';
require SITE_FORMS . 'Form_Element_Text_Empresa.php';
require SITE_FORMS . 'Form_Element_Text_Endereco.php';
require SITE_FORMS . 'Form_Element_Text_Nome.php';
require SITE_FORMS . 'Form_Element_Text_Site.php';
require SITE_FORMS . 'Form_Element_Text_Telefone.php';
require SITE_FORMS . 'Form_Element_Textarea_Observacao.php';

class SubFormulario_Inscreva extends Zend_Form_SubForm
{
public function init()
{
// Nome
$nome = new Form_Element_Text_Nome('nome');
$nome->setDecorators(array(
        'ViewHelper'
          , 'Errors'
  , array('decorator' => array('td' => 'HtmlTag'), 'options' => array('tag' => 'td'))
  , array('Label', array('tag' => 'th'))
  , array('decorator' => array('tr' => 'HtmlTag'), 'options' => array('tag' => 'tr'))
  )
);

// Empresa
$empresa = new Form_Element_Text_Empresa('empresa');
$empresa->setDecorators(array(
        'ViewHelper'
          , 'Errors'
  , array('decorator' => array('td' => 'HtmlTag'), 'options' => array('tag' => 'td'))
  , array('Label', array('tag' => 'th'))
  , array('decorator' => array('tr' => 'HtmlTag'), 'options' => array('tag' => 'tr'))
  )
);

// CPF/CNPJ
$cpfcnpj = new Form_Element_Text_CPFCNPJ('cpfcnpj');
$cpfcnpj->setDecorators(array(
        'ViewHelper'
          , 'Errors'
  , array('decorator' => array('td' => 'HtmlTag'), 'options' => array('tag' => 'td'))
  , array('Label', array('tag' => 'th'))
  , array('decorator' => array('tr' => 'HtmlTag'), 'options' => array('tag' => 'tr'))
  )
);

// Endereço
$endereco = new Form_Element_Text_Endereco('endereco');
$endereco->setDecorators(array(
        'ViewHelper'
          , 'Errors'
  , array('decorator' => array('td' => 'HtmlTag'), 'options' => array('tag' => 'td'))
  , array('Label', array('tag' => 'th'))
  , array('decorator' => array('tr' => 'HtmlTag'), 'options' => array('tag' => 'tr'))
  )
);

// Bairro
$bairro = new Form_Element_Text_Bairro('bairro');
$bairro->setDecorators(array(
        'ViewHelper'
          , 'Errors'
  , array('decorator' => array('td' => 'HtmlTag'), 'options' => array('tag' => 'td'))
  , array('Label', array('tag' => 'th'))
  , array('decorator' => array('tr' => 'HtmlTag'), 'options' => array('tag' => 'tr'))
  )
);

// Cidade
$cidade = new Form_Element_Text_Cidade('cidade');
$cidade->setDecorators(array(
        'ViewHelper'
          , 'Errors'
  , array('decorator' => array('td' => 'HtmlTag'), 'options' => array('tag' => 'td'))
  , array('Label', array('tag' => 'th'))
  , array('decorator' => array('tr' => 'HtmlTag'), 'options' => array('tag' => 'tr'))
  )
);

// Estado
$estado = new Form_Element_Select_Estado('estado');
$estado->setDecorators(array(
        'ViewHelper'
          , 'Errors'
  , array('decorator' => array('td' => 'HtmlTag'), 'options' => array('tag' => 'td'))
  , array('Label', array('tag' => 'th'))
  , array('decorator' => array('tr' => 'HtmlTag'), 'options' => array('tag' => 'tr'))
  )
);

// Telefone
$telefone = new Form_Element_Text_Telefone('telefone');
$telefone->setDecorators(array(
        'ViewHelper'
          , 'Errors'
  , array('decorator' => array('td' => 'HtmlTag'), 'options' => array('tag' => 'td'))
  , array('Label', array('tag' => 'th'))
  , array('decorator' => array('tr' => 'HtmlTag'), 'options' => array('tag' => 'tr'))
  )
);

// E-mail
$email = new Form_Element_Text_Email('email');
$email->setDecorators(array(
        'ViewHelper'
          , 'Errors'
  , array('decorator' => array('td' => 'HtmlTag'), 'options' => array('tag' => 'td'))
  , array('Label', array('tag' => 'th'))
  , array('decorator' => array('tr' => 'HtmlTag'), 'options' => array('tag' => 'tr'))
  )
);

// Site
$site = new Form_Element_Text_Site('site');
$site->setDecorators(array(
        'ViewHelper'
          , 'Errors'
  , array('decorator' => array('td' => 'HtmlTag'), 'options' => array('tag' => 'td'))
  , array('Label', array('tag' => 'th'))
  , array('decorator' => array('tr' => 'HtmlTag'), 'options' => array('tag' => 'tr'))
  )
);

// Site
$formaPagamento = new Form_Element_Radio_Formapagamento('formaPagamento');
$formaPagamento->setDecorators(array(
        'ViewHelper'
          , 'Errors'
  , array('decorator' => array('td' => 'HtmlTag'), 'options' => array('tag' => 'td'))
  , array('Label', array('tag' => 'th'))
  , array('decorator' => array('tr' => 'HtmlTag'), 'options' => array('tag' => 'tr', 'valign' => 'top'))
  )
);

// Observação
$observacao = new Form_Element_Textarea_Observacao('observacao');
$observacao->setDecorators(array(
    'ViewHelper'
  , 'Errors'
  , array('decorator' => array('td' => 'HtmlTag'), 'options' => array('tag' => 'td'))
  , array('Label', array('tag' => 'th'))
  , array('decorator' => array('tr' => 'HtmlTag'), 'options' => array('tag' => 'tr', 'valign' => 'top'))
      ));

$this->setDecorators(
array('FormElements', array('HtmlTag', array('tag' => 'table', 'cellspacing' => 1)))
);

        $this->addElements(
array($nome
                ,$empresa
                ,$cpfcnpj
                ,$endereco
                ,$bairro
                ,$cidade
                ,$estado
                ,$telefone
                ,$email
                ,$site
                ,$formaPagamento
                ,$observacao
        )
    );

}
}



Quote

2. How to deal with tabular data input?

This is a great nightmare in Zend Framework world...
You must google for an entire day and find only one article explaining...

You can have 2 options.
1 - Let the object render their selves with Decorators,  subforms and they element (text, radio..) with pre-set html wrappers.
Good for simple form.
Bad for a little complex form.

2 - You can do a viewscript: http://framework.zen...tors.viewScript

You make a template and renders each html element in they respective position.

Quote

3. How to group form elements?

I think this was answered in 1.
0

#5 User is offline   pestaa 

  • past Yii dev member
  • PipPipPipPip
  • Yii
  • Group: Members
  • Posts: 705
  • Joined: 07-May 09
  • Location:Hungary

Posted 20 June 2009 - 12:26 PM

Zend Framework is a mass of code, this example requires nearly 20 files, which is insane for a single form.

Tabular data should be collected from multiple CForms. What about CTabularForm, which would be a wrapper for many CForms to decrease the latter's complexity?

Is it possible to call CForm's constructor with an array instead of a path to the specification?

Thanks for your fantastic piece of work!
0

#6 User is offline   skyblaze 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 106
  • Joined: 07-January 09

Posted 21 June 2009 - 04:53 AM

Quote

I have experience with Zend Framework and I can say is Yii shall get inspiration from it.



1. How to represent a form involving several models?


Like form and subforms: http://framework.zen...form.forms.html



Take a look how is simple in zend framework:

This is FORM (base)

<?php

require SITE_FORMS . 'SubFormulario_Inscreva.php';
require SITE_FORMS . 'SubFormulario_MaisPessoas.php';

class Formulario_Inscreva extends Zend_Form
{
public function init()
{
$this->setAction('')
    ->setMethod('post');

$inscreva    = new SubFormulario_Inscreva();
$maispessoas = new SubFormulario_MaisPessoas();

$this->addSubForm($inscreva  , 'inscreva');
$this->addSubForm($maispessoas, 'maispessoas');

$submit = new Zend_Form_Element_Submit('submit');
$submit->setLabel('Enviar')
->setDecorators(array(
array(
'decorator' => 'ViewHelper',
'options' => array('helper' => 'formSubmit')),
array(
'decorator' => array('td' => 'HtmlTag'),
'options' => array('tag' => 'td', 'colspan' => 2)),
array(
'decorator' => array('tr' => 'HtmlTag'),
'options' => array('tag' => 'tr')),
array(
'decorator' => array('table' => 'HtmlTag'),
'options' => array('tag' => 'table')),
    ));

$this->setDecorators(
array('FormElements'
  , array('Form')
)
);

        $this->addElements(
array($submit
        )
    );

}
}




This is one of sub-form attached in base form

<?php

/**
*  Nome
    *  Empresa
    *  CPF/CNPJ
    *  Endereço
    *  Bairro
    *  Cidade
    *  Estado
    *  Telefone
    *  E-mail
    *  Site
    *  Forma de pagamento
    *  Observação
    *
    *  Sub-Formulário
    *      Nome Completo
    *      Nome para Crachá
    *      E-mail
*/

require SITE_FORMS . 'Form_Element_Radio_Formapagemento.php';
require SITE_FORMS . 'Form_Element_Select_Estado.php';
require SITE_FORMS . 'Form_Element_Text_Bairro.php';
require SITE_FORMS . 'Form_Element_Text_CPFCNPJ.php';
require SITE_FORMS . 'Form_Element_Text_Cidade.php';
require SITE_FORMS . 'Form_Element_Text_Email.php';
require SITE_FORMS . 'Form_Element_Text_Empresa.php';
require SITE_FORMS . 'Form_Element_Text_Endereco.php';
require SITE_FORMS . 'Form_Element_Text_Nome.php';
require SITE_FORMS . 'Form_Element_Text_Site.php';
require SITE_FORMS . 'Form_Element_Text_Telefone.php';
require SITE_FORMS . 'Form_Element_Textarea_Observacao.php';

class SubFormulario_Inscreva extends Zend_Form_SubForm
{
public function init()
{
// Nome
$nome = new Form_Element_Text_Nome('nome');
$nome->setDecorators(array(
        'ViewHelper'
          , 'Errors'
  , array('decorator' => array('td' => 'HtmlTag'), 'options' => array('tag' => 'td'))
  , array('Label', array('tag' => 'th'))
  , array('decorator' => array('tr' => 'HtmlTag'), 'options' => array('tag' => 'tr'))
  )
);

// Empresa
$empresa = new Form_Element_Text_Empresa('empresa');
$empresa->setDecorators(array(
        'ViewHelper'
          , 'Errors'
  , array('decorator' => array('td' => 'HtmlTag'), 'options' => array('tag' => 'td'))
  , array('Label', array('tag' => 'th'))
  , array('decorator' => array('tr' => 'HtmlTag'), 'options' => array('tag' => 'tr'))
  )
);

// CPF/CNPJ
$cpfcnpj = new Form_Element_Text_CPFCNPJ('cpfcnpj');
$cpfcnpj->setDecorators(array(
        'ViewHelper'
          , 'Errors'
  , array('decorator' => array('td' => 'HtmlTag'), 'options' => array('tag' => 'td'))
  , array('Label', array('tag' => 'th'))
  , array('decorator' => array('tr' => 'HtmlTag'), 'options' => array('tag' => 'tr'))
  )
);

// Endereço
$endereco = new Form_Element_Text_Endereco('endereco');
$endereco->setDecorators(array(
        'ViewHelper'
          , 'Errors'
  , array('decorator' => array('td' => 'HtmlTag'), 'options' => array('tag' => 'td'))
  , array('Label', array('tag' => 'th'))
  , array('decorator' => array('tr' => 'HtmlTag'), 'options' => array('tag' => 'tr'))
  )
);

// Bairro
$bairro = new Form_Element_Text_Bairro('bairro');
$bairro->setDecorators(array(
        'ViewHelper'
          , 'Errors'
  , array('decorator' => array('td' => 'HtmlTag'), 'options' => array('tag' => 'td'))
  , array('Label', array('tag' => 'th'))
  , array('decorator' => array('tr' => 'HtmlTag'), 'options' => array('tag' => 'tr'))
  )
);

// Cidade
$cidade = new Form_Element_Text_Cidade('cidade');
$cidade->setDecorators(array(
        'ViewHelper'
          , 'Errors'
  , array('decorator' => array('td' => 'HtmlTag'), 'options' => array('tag' => 'td'))
  , array('Label', array('tag' => 'th'))
  , array('decorator' => array('tr' => 'HtmlTag'), 'options' => array('tag' => 'tr'))
  )
);

// Estado
$estado = new Form_Element_Select_Estado('estado');
$estado->setDecorators(array(
        'ViewHelper'
          , 'Errors'
  , array('decorator' => array('td' => 'HtmlTag'), 'options' => array('tag' => 'td'))
  , array('Label', array('tag' => 'th'))
  , array('decorator' => array('tr' => 'HtmlTag'), 'options' => array('tag' => 'tr'))
  )
);

// Telefone
$telefone = new Form_Element_Text_Telefone('telefone');
$telefone->setDecorators(array(
        'ViewHelper'
          , 'Errors'
  , array('decorator' => array('td' => 'HtmlTag'), 'options' => array('tag' => 'td'))
  , array('Label', array('tag' => 'th'))
  , array('decorator' => array('tr' => 'HtmlTag'), 'options' => array('tag' => 'tr'))
  )
);

// E-mail
$email = new Form_Element_Text_Email('email');
$email->setDecorators(array(
        'ViewHelper'
          , 'Errors'
  , array('decorator' => array('td' => 'HtmlTag'), 'options' => array('tag' => 'td'))
  , array('Label', array('tag' => 'th'))
  , array('decorator' => array('tr' => 'HtmlTag'), 'options' => array('tag' => 'tr'))
  )
);

// Site
$site = new Form_Element_Text_Site('site');
$site->setDecorators(array(
        'ViewHelper'
          , 'Errors'
  , array('decorator' => array('td' => 'HtmlTag'), 'options' => array('tag' => 'td'))
  , array('Label', array('tag' => 'th'))
  , array('decorator' => array('tr' => 'HtmlTag'), 'options' => array('tag' => 'tr'))
  )
);

// Site
$formaPagamento = new Form_Element_Radio_Formapagamento('formaPagamento');
$formaPagamento->setDecorators(array(
        'ViewHelper'
          , 'Errors'
  , array('decorator' => array('td' => 'HtmlTag'), 'options' => array('tag' => 'td'))
  , array('Label', array('tag' => 'th'))
  , array('decorator' => array('tr' => 'HtmlTag'), 'options' => array('tag' => 'tr', 'valign' => 'top'))
  )
);

// Observação
$observacao = new Form_Element_Textarea_Observacao('observacao');
$observacao->setDecorators(array(
    'ViewHelper'
  , 'Errors'
  , array('decorator' => array('td' => 'HtmlTag'), 'options' => array('tag' => 'td'))
  , array('Label', array('tag' => 'th'))
  , array('decorator' => array('tr' => 'HtmlTag'), 'options' => array('tag' => 'tr', 'valign' => 'top'))
      ));

$this->setDecorators(
array('FormElements', array('HtmlTag', array('tag' => 'table', 'cellspacing' => 1)))
);

        $this->addElements(
array($nome
                ,$empresa
                ,$cpfcnpj
                ,$endereco
                ,$bairro
                ,$cidade
                ,$estado
                ,$telefone
                ,$email
                ,$site
                ,$formaPagamento
                ,$observacao
        )
    );

}
}






Quote

2. How to deal with tabular data input?


This is a great nightmare in Zend Framework world...

You must google for an entire day and find only one article explaining...



You can have 2 options.

1 - Let the object render their selves with Decorators,  subforms and they element (text, radio..) with pre-set html wrappers.

Good for simple form.

Bad for a little complex form.



2 - You can do a viewscript: http://framework.zen...tors.viewScript



You make a template and renders each html element in they respective position.



Quote

3. How to group form elements?


I think this was answered in 1.

The CForm idea from qiang is nice.
But please don't do the form thing as in the zend framework it is a nightmare!! I left zend framework mainly for its form management. It is impossibile to customize the html in the form without becoming crazy with decorators  etc.
0

#7 User is offline   qiang 

  • Yii Project Lead
  • Yii
  • Group: Yii Dev Team
  • Posts: 5,874
  • Joined: 04-October 08
  • Location:DC, USA

Posted 21 June 2009 - 06:15 AM

Thank you for the reference to Zend_Form. Yes, I did study it a little bit and also similar feature in other frameworks. I agree that we should not put too much logic and presentation in the form object. While Zend_Form does offer maximum flexibility, its usage is overly complicated and may not be practical as well.

The idea of Yii form is very simple: the form only contains specification of input fields. We let data models to do biz logic, let views to do presentation, and controller to be responsible for binding them all.
0

#8 User is offline   pestaa 

  • past Yii dev member
  • PipPipPipPip
  • Yii
  • Group: Members
  • Posts: 705
  • Joined: 07-May 09
  • Location:Hungary

Posted 21 June 2009 - 06:22 AM

Will be there any cases when one has to check whether the $form->submitted() without loading the data into it?
0

#9 User is offline   qiang 

  • Yii Project Lead
  • Yii
  • Group: Yii Dev Team
  • Posts: 5,874
  • Joined: 04-October 08
  • Location:DC, USA

Posted 21 June 2009 - 06:50 AM

Yes, you can do that. The two lines are equivalent to:

if(isset($_POST['submitButton']))
    $model->attributes=$_POST['ModelClass'];


0

#10 User is offline   pestaa 

  • past Yii dev member
  • PipPipPipPip
  • Yii
  • Group: Members
  • Posts: 705
  • Joined: 07-May 09
  • Location:Hungary

Posted 21 June 2009 - 07:13 AM

Sorry if I was misunderstable. Could $form->submitted() be implemented in such way so that automatically loads data?
0

#11 User is offline   dalip 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 54
  • Joined: 21-December 08

Posted 21 June 2009 - 07:16 AM

I like it. I have thought about a form class for Yii for a while but am way to busy with other things to spend any time doing php.

Anyway, might it also be possible to pass an object instead of specfile so as to facilitate easy dynamic forms. For example

$model=new LoginFormModel;
$formspec=new CFormSpec;
$formspec->addTextField('username',array('maxlength'=>80));
$formspec->addPasswordField('username',array('maxlength'=>80));
$form=new CForm($model, $formspec);


0

#12 User is offline   pestaa 

  • past Yii dev member
  • PipPipPipPip
  • Yii
  • Group: Members
  • Posts: 705
  • Joined: 07-May 09
  • Location:Hungary

Posted 21 June 2009 - 07:20 AM

dalip

I wanted to do the same, but only with arrays. Why add additional levels of abstraction?
0

#13 User is offline   qiang 

  • Yii Project Lead
  • Yii
  • Group: Yii Dev Team
  • Posts: 5,874
  • Joined: 04-October 08
  • Location:DC, USA

Posted 21 June 2009 - 07:25 AM

Right now the main problem I am considering is how to reuse CHtml in CForm. My original proposal uses widgets as input types, which would require us to implement a widget for every active* method in CHtml.
0

#14 User is offline   qiang 

  • Yii Project Lead
  • Yii
  • Group: Yii Dev Team
  • Posts: 5,874
  • Joined: 04-October 08
  • Location:DC, USA

Posted 21 June 2009 - 07:27 AM

Quote

Sorry if I was misunderstable. Could $form->submitted() be implemented in such way so that automatically loads data?


Yes, we could add a parameter to submitted() that may indicate loading data or not.
0

#15 User is offline   dalip 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 54
  • Joined: 21-December 08

Posted 21 June 2009 - 10:03 AM

Quote

Right now the main problem I am considering is how to reuse CHtml in CForm. My original proposal uses widgets as input types, which would require us to implement a widget for every active* method in CHtml.

The fiddling I did a while ago with form generation gave me the same impression. Any idea on how to handle labels?
0

#16 User is offline   qiang 

  • Yii Project Lead
  • Yii
  • Group: Yii Dev Team
  • Posts: 5,874
  • Joined: 04-October 08
  • Location:DC, USA

Posted 21 June 2009 - 10:30 AM

label is not a problem because we can get it from the model behind. We still provide the 'label' property for each element which can be used to override the label obtained from model.
0

#17 User is offline   Ismael 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 163
  • Joined: 02-June 09
  • Location:Brazil

Posted 21 June 2009 - 11:07 AM

Quote

Right now the main problem I am considering is how to reuse CHtml in CForm. My original proposal uses widgets as input types, which would require us to implement a widget for every active* method in CHtml.


I think this is the right way to go.

The final user should only know how to use it and don't concerd if it has thousand widgets.

In the end, it will be severial widgets using helpers. They would have minimal line of codes.
0

#18 User is offline   skyblaze 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 106
  • Joined: 07-January 09

Posted 22 June 2009 - 02:00 AM

Quote

Thank you for the reference to Zend_Form. Yes, I did study it a little bit and also similar feature in other frameworks. I agree that we should not put too much logic and presentation in the form object. While Zend_Form does offer maximum flexibility, its usage is overly complicated and may not be practical as well.



The idea of Yii form is very simple: the form only contains specification of input fields. We let data models to do biz logic, let views to do presentation, and controller to be responsible for binding them all.
exactly. For me this way will be perfect for CForm ;)
0

#19 User is offline   amc 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 46
  • Joined: 13-March 09

Posted 23 June 2009 - 05:19 PM

Surely proper use of partials will reduce duplication in form design. Is this proposal not complicating things slightly :-\
0

#20 User is offline   jonah 

  • Advanced Member
  • Yii
  • Group: Yii Dev Team
  • Posts: 733
  • Joined: 27-November 08
  • Location:California (US)

Posted 23 June 2009 - 06:56 PM

This is the way I could imagine it:

A widget class is made for every type of field.  There will be a CPasswordField, CTextField etc.  These classes will inherit from CField which in turn inherits from CFieldBaseCFieldBase will contain any shared logic between the field classes.  CField will be a dummy class which the user can override in his app in order to extend all field classes.

CFieldBase should contain an internal method getLabel() that gets the label from the model.  It is used if the label is not overridden in the form config array.  This way the user could override this method in CField, for instance to add a period at the end of the label, or make it uppercase.  Edit:  Actually maybe the labels would be better to be modified in the view?

CHtml active*Field() methods would simply call the corresponding widget class (they would basically be wrappers).

Spec (form config) files should be able to have arbitrary options like so:
return array(
  'username'=>array(
      'label'=>'Username', // optional, would be determined by model
      'required'=>true,    // optional, would be determined by model
      'type'=>'CTextField',// optional, CTextField
      'tooltip'=>'tooltip info here',
      'maxlength'=>80,
  ),
);

So that in the view file you can reference this:
<?php
$form->begin();
foreach($form->elements as $element)
{
  echo $element->label."<br/>".$element->render()."<br/>";
  if ($element->tooltip) echo "<div class="tooltip">$element->tooltip</div>";  //<--
  echo $element->error;
}
$form->end();

0

Share this topic:


  • (3 Pages)
  • +
  • 1
  • 2
  • 3
  • You cannot start a new topic
  • You cannot reply to this topic

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users