Zend framework custom Form decorators
Posted by Faheem Abbas on November 13, 2008
Zend framework custom Form decorators
Recently when I posted an article on Zend Form decorators as well as Zend Form display group decorators, hundred of developers visit that post. This clearly indicate that developers using Zend_Form to create html form are having difficulties in using decorators.
Although I have created very nice and fancy forms using display groups and decorators in one of my application using the methods I’ve previously discussed. However as most developers are having problems using decorators I decided to wit my hands and take a deeper look it into this topic.
Although Zend framework documentation is extremely helpful and give comprehensive knowledge of how to use different components shipped with it, however most of developer find it hard because of lack of examples, I think.
I say this because I wasn’t able to properly following it and take benefits out of it in the beginning.
Few days back I studied how to create and use our own custom decorators. Studying the topic for about some time I came to the conclusion that it is quite easy to create and implement our own decorator. Creating and using your own decorators give the ability to layout your form what ever way you like.
In this post I am going to give you a very simple example of how to create and then use you own decorators.
So lets get started.
Before define our own decorators I would like to tell you that the standard decorators shipped with Zend Framework can be found in Zend/Form/Decorators. This directory contains an abstract class Zend_Form_Decorator_Abstract that is extend by all the standard decorators.
To define our own custom decorator class we will also need to extend our class form the same abstract class.
Before writing the code, create My/Form/Decorators/ directory structure under /library folder in your application.
Now create Simple.php and place the following code in it.
class My_Form_Decorators_Simple extends Zend_Form_Decorator_Abstact
{Public function render($content)
{$element = $this->getElement();
if(!$element instanceof Zend_Form_Element){
return $content;}
if(null = = = $element->getView()){
return $content;}
$seperator = $this->getSeperator();
$placement = $this->getPlacement();
$label = $this->buildLabel();
$label = $this->buildInput();
$label = $this->buildErrors();
$label = $this->buildDescription();$output=’
. $label
. $input
.$errors
.$decs
.’ ’;switch($placement)
{case (self::PREPEND):return $output.$seperator.$content;
break;case (self::APPEND):default:return $content.$seperator.$output;
break;}
}
public function buildLabel()
{$element=$this->getElement();
$label=$element->getLabel();
if($transtalor=$element->getTranslator()){$label = $translator->translate($label);
}
if($element->isRequired()){
$label .= ‘*’;
}
$label .= ‘:’;
return $element->getView()->formLabel($element->getName(),$label);
}
public function buildInput()
{$element = $this->getElement();
$helper = $this->helper;
return $element->getView()->$helper($element->getName(),
$element->getValue(),
$element->getAttribs(),
$element->getOptions(),);
}
function buildErrors()
{$element $this->getElement();
$messages = $element->getMessages();if(empty($messages)){
return ”;
}
return ” . $element->getView()->formErrors($messages).”;
}public function buildDescription()
{$element = $this->getElement();
$desc = $element->getDescription();
if(empty($desc)){return ”;
}
return ”.$desc.”;
}
}
?>
Explanation:
The code is not I think hard to understand.
Whenever you apply decorator using setDecorators() methd, View called render($content) method of Zend_Form_Decorator_Abstact at the time of rendering form.
In the code above we first extend our custom decorator class form Zend_Form_Decorator_Abstact and then define our our render() function. so when we apply this custom decorator to any of our element in the form, view will call this render() method.
In our fist few line of render method we get element(by using getElement() function) and check whether or not it is instance of the Zend_Form_Element using instanceof operator. If not then we simply return the contents passed to this function. we also check the view(by using getView method on $element).
Next we get separator and placement. Placement can be either prepand or append(by default).
The next few lines are important.
We call four method buildLabel(), buildInput(), buildErrors() and buildDescription();
The buildLabel() method apply decorators to the Lable of the element. In this method we first get the element and then label. If translator is applied we translate the label. If it is required we concatenate “*” with the label and then “:” colon.
At the end we return the label.
buildInput() apply decorators to the inputbox/checkbox/radion etc.
the code is simple, we get element and helper and then return the elements with its value, attribs and options.
buildErrors() apply decorators to the errors if any. As usual we get element, get error message if any and then return errors messages in div.
buildDescripiton() method check for the description and return it in the div if any.
That’s it our own custom decorator class.
Next we will need to apply this to our Zend_Form elements.
Let you have the following form
class MyForm extents Zend_Form
{public function __construct($options=array())
{parent::__construct($options);
$username = $this->CreateElement(’text’,'username’);
$username->setLabel()->setDecription(’Required’);
}
}
?>
To apply the above custom decorator write
$this->addElementPrefixPath(’My_Form_Decorators’,
‘My/Form/Decorator’,
‘decorator’);
after parent::__construct($options); in your constructor.
and replace
$username = $this->CreateElement(’text’,'username’);
$username->setLabel()->setDecription(’Required’);
With
$username = $this->CreateElement(’text’,'username’);
$username->setLabel()->setDecription(’Required’)
->setDecorators(array(’Simple’));
That’s it. We have now applied our custom decorator to our form element. You can apply this custom decorator to as many form element as you like.
Mr. Magic said
Have you ever tried reading one of your posts yourself? It’s pretty fun to read text with absolutely no spaces in between clauses…
Streamer said
Thank you for this article, a tryied to solve my problem with decorators few mounts ago but only this article helps me how to create it, thanks (sorry for my english)
Hab said
I’m a newbie in ZF. I’ve created my first application with the help http://framework.zend.com/docs/quickstart an I tried to add custom decorator with the help this article.. but it’s getting error “Message: Decorator by name Label does not exist”..
Any idea?
Thanks
Hab
Hab said
I’ve tried this
$this->Name->addDecorator(’Simple’);
But got this error
Parse error: syntax error, unexpected T_SWITCH in E:\wamp\www\matri\library\My\Form\Decorators\Simple.php on line 76
Hab said
I’ve tried addDecorators(array(’Simple’));
but got error
Warning: Zend_Loader::include_once(Zend\Form\Decorator\Abstact.php) [zend-loader.include-once]: failed to open stream: No such file or directory in E:\wamp\www\matri\library\Zend\Loader.php on line 84
Warning: Zend_Loader::include_once() [function.include]: Failed opening ‘Zend\Form\Decorator\Abstact.php’ for inclusion (include_path=’E:\wamp\www\matri\application/../library;.;C:\php5\pear’) in E:\wamp\www\matri\library\Zend\Loader.php on line 84
Fatal error: Class ‘Zend_Form_Decorator_Abstact’ not found in E:\wamp\www\matri\library\My\Form\Decorators\Simple.php on line 2
But Abstact.php is there at Zend\Form\Decorator\
Jesse said
Can someone tell me what the ini file config looks like for this?
I’m trying something like this
userForm.elements.name_first.type = “text”
userForm.elements.name_first.options.label = “Name First”
userForm.elements.name_first.options.validators.notempty.validator = “NotEmpty”
userForm.elements.name_first.options.validators.notempty.options.messages.isEmpty = “A valid user name is required.”
userForm.elements.name_first.options.elementprefixPath.my.type = “decorator”
userForm.elements.name_first.options.elementprefixPath.my.path = “My/Form/Decorator/”
userForm.elements.name_first.options.elementprefixPath.my.prefix = “My_Form_Decorator”
userForm.elements.name_first.options.decorator = “Simple”