Sunday, June 28, 2009

highlight not validated fields with a decorator

I started using the Zend Framework few weeks ago, finally finished my first project using it at work last week. I am quiet happy with the framework and really enjoyed coding this application, I have made bunch of class that I found missing in the framework.

One of them was to be able to add a specific class when some fields in a form doesn't validate, I use to highlight fields when the user forgot to input them in my previous projects.

He wasn't so easy to code that decorator because in the framework decorator doesn't seem to be able to add some attributes to the field. Normal decorators can append of prepend some content but not change options of the fields. Here the hack I have been doing to achieve my goal.


require_once 'Zend/Form/Decorator/Abstract.php';
/**
* This decorator add a decorator which add a custom class to the input
*
* @author olivier
*/

class Trust_Form_Decorator_ClassErrors extends Zend_Form_Decorator_Abstract{

 public function render($content)
 {
     $element = $this->getElement();
 
     if(!$element instanceof Zend_Form_Element_Password &&
        !$element instanceof Zend_Form_Element_Text &&
        !$element instanceof Zend_Form_Element_Textarea &&
        !$element instanceof Trust_Form_Element_Telephone ){
         return $content;   
     }
 
     $view    = $element->getView();
     if (null === $view) {
         return $content;
     }
 
     $attribs   = $element->getAttribs();
 
     $errors = $element->getMessages();
     if (empty($errors)) {
         return $content;
     }

     if(isset($this->_options['class'])){
         $errorClass = $this->getOption('class');
     } else {
         $errorClass = 'customError';
     }
     if($element instanceof Zend_Form_Element_Password ||
        $element instanceof Zend_Form_Element_Text ||
        $element instanceof Trust_Form_Element_Telephone ){
            $tag = 'input';
     } else {
         $tag = 'textarea';
     }
 
     if(isset($attribs['class'])){
         $content = preg_replace('/<'.$tag.'([^>]*)class="[^"]*"([^>]*)>/', '<'.$tag.' class="' . $errorClass . ' ' . $attribs['class'] . '"$1 $2>', $content);
     } else {
         $content = preg_replace('/<'.$tag.'([^>]*)([^>]*)>/', '<'.$tag.' class="' . $errorClass .'"$1>', $content);
     }
  
     return $content;
 }
}

This code add a class "customError" (or any name you specified in option) to the field if it didn't validate