I want use decorators to format as table the following Zend_Form, placing a description in the first column and the Zend_Form_Element_Radio\'s opti
Well here my version of the answer.
Into the init I've add a custom decorator RadioTable to the form, and prefix path to load the decorator
then I decorate all the elements as a normal table, this's important because all my efforts are to keep the facilities offer by standard decorators like "Error"
Please note the Custom_Form_Element_FirstSelect and the ->setSeparator in the radio element
I also add the submit button
public function init()
{
$_please_select = array("" => " please select ");
// I add a my custom decorator
$this->addPrefixPath('Custom_Form_Decorator',
'Custom/Form/Decorator',
'decorator');
$this->setMethod(Zend_Form::METHOD_POST);
$input_lunch = new Zend_Form_Element_Radio('lunch');
$input_lunch ->setMultiOptions(self::$KINDS)
->setSeparator("\t__RADIO_SEPARATOR__\t") //set custom separator I'll use in custom decorator
->setDecorators(array(
'ViewHelper', // add a standard decorator
'Label', // I'll use the label decorator to show text
));
$this->addElement($input_lunch );
foreach (self::$KINDS as $k => $_description) {
// to "mark" the first select I extend the Zend_Form_Element_Select
// with Custom_Form_Element_FirstSelect
$input_drink = new Custom_Form_Element_FirstSelect('drink_' . $k);
$input_drink->addMultiOptions(self::$DRINKS)
->setDecorators(array(
'ViewHelper', // add a standard decorator
array(array('data' => 'HtmlTag'),array('tag' => 'td')), // add a standard decorator
));
$input_food = new Zend_Form_Element_Select('food_' . $k);
$input_food->addMultiOptions($_please_select)
->addMultiOptions(self::$FOODS)
->setDecorators(array(
'ViewHelper',
array(array('data' => 'HtmlTag'),array('tag' => 'td')),
));
$this->addElement($input_drink);
$this->addElement($input_food);
}
// add a the submit button
$submit = new Zend_Form_Element_Submit('submit');
$submit->setLabel('SUBMIT');
$submit->setDecorators(array(
'ViewHelper',
'Errors',
array(array('data' => 'HtmlTag'), array('tag' => 'td', )),
array(array('row' => 'HtmlTag'), array('tag' => 'tr')),
));
$this->addElement($submit);
// add the custom decorators to the whole form
$this->setDecorators(array(
'RadioTable',
array('HtmlTag', array('tag' => 'table', )),
'Form'
));
}
the Custom_Form_Element_FirstSelect
class Custom_Form_Element_FirstSelect extends Zend_Form_Element_Select{
}
the Custom_Form_Decorator_RadioTable
class Custom_Form_Decorator_RadioTable extends Zend_Form_Decorator_Abstract {
public function render($content){
$wrap = '';
// I'll take the element
$radioElement = $this->getElement()->getElement('lunch');
// then I render it and explode in array using the separator
$arrayRadio = explode("\t__RADIO_SEPARATOR__\t", $radioElement->__toString());
$count = 0;
$arrayElement = $this->getElement()->getElements();
// loop on all form elements and I render them
foreach ($arrayElement as $keyForm => $element){
// I skip the radio element
if($element instanceof Zend_Form_Element_Radio){
continue;
}
if($element instanceof Custom_Form_Element_FirstSelect ){
// when I found the custom select element I'll prefix with "open-row-tag" and radio button in column
$wrap .= "". "". $arrayRadio[$count++] . " " . $element->__toString();
// note that the select elements are already decorated
} else if($element instanceof Zend_Form_Element_Select){
// after the last select I close the row
$wrap .= $element->__toString() ." ";
}
if($element instanceof Zend_Form_Element_Submit){
// add the SUBMIT button
$wrap .= $element->__toString() ;
}
}
return $content.$wrap;
}
}
Of course I can use the name of the element instead of use a custom element class to open the table row, but in this way I'm feel more flexible.