Zend: wrap FormErrors with user-defined html tags

2019-06-14 04:42发布

问题:

Zend talk.By default,using the FormErrors decorator the generated list of errors has the following markup:

<ul class="form-errors>
 <li>
  <b>[element label or name]</b>
  <ul>
    <li>[error message]</li>
    <li>[error message]</li>
  </ul>
 </li>
</ul>

Question: How can I use the following structure instead?

<span class='myErrors'>
 &bull;[error message]</br>
</span>

Update: I tried with:

array('FormErrors', array(
'markupListStart' => "<span class='myErrors'>",
'markupListEnd' => '</span>',
'markupListItemStart' => '',
'markupListItemEnd' => '</br>',
'ignoreSubForms'=> false,
'showCustomFormErrors' => true,
'onlyCustomFormErrors'=> false,
'markupElementLabelEnd'   => '',
'markupElementLabelStart' => ''
));

But I still have unwanted tags and labels.This is the source code:

<span class='myErrors'>
 [element label or name]
 <ul class="errors">
  <li>
  [error message]
  </li>
</ul>
</br>
</span>

回答1:

The simples thing would be to create own decorator. You can take Zend decorator and modify the code. But I would recommend to put the messages in

element instead of for the sake of semantics, span is after all an in-line element and you want to make multiple lines.

If you do not want to create new decorator you can try pass an array with data like in the Zend FormErrors options

protected $_defaults = array(
    'ignoreSubForms'          => false,
    'showCustomFormErrors'    => true,
    'onlyCustomFormErrors'    => false,
    'markupElementLabelEnd'   => '</b>',
    'markupElementLabelStart' => '<b>',
    'markupListEnd'           => '</ul>',
    'markupListItemEnd'       => '</li>',
    'markupListItemStart'     => '<li>',
    'markupListStart'         => '<ul class="form-errors">',
);

Create similar array with appropriate tags.



回答2:

You need two things: A decorator and a view helper. By default Zend Form uses the 'Errors' decorator, which uses the FormErrors view helper. You need to override this to achieve what you need. Take this simple example to illustrate this:

class Admin_Form_Authors extends Zend_Form
{

    public function init()
    {

        $name = new Zend_Form_Element_Text('name');
        $name->setLabel('name')
             ->setRequired(true)
             ->addFilter('StripTags')
             ->addFilter('StringTrim')
             ->addValidator('NotEmpty')
             ->setDecorators(array(
                'ViewHelper',
                array(new My_Form_Error_Decorator(),array('class' => 'my-error','escape' => true)),
                'Label',
                'HtmlTag'
                ));

        $submit = new Zend_Form_Element_Submit('submit');
        $submit->setAttrib('id','submitbutton');

        $this->addElements(array($name,$submit));
    }
}

As you can see, the second decorator I'm using for my $name form element, is an new object of My_Form_Error_Decorator class, which looks something like this:

class My_Form_Error_Decorator extends Zend_Form_Decorator_Abstract
{
    public function render($content)
     {
        $element = $this->getElement();
        $view    = $element->getView();
        if (null === $view) {
            return $content;
        }

        $errors = $element->getMessages();
        if (empty($errors)) {
            return $content;
        }

        $separator = $this->getSeparator();
        $placement = $this->getPlacement();
        $viewhelp = new My_Form_Error_View_Helper();
        $errors = $viewhelp->myErrorViewer($errors, $this->getOptions());

        switch ($placement) {
            case self::APPEND:
                return $content . $separator . $errors;
            case self::PREPEND:
                return $errors . $separator . $content;
        }
     }

}

This is in fact almost the same decorator as the default 'Errors' decorator, the only line I change is this $errors = $viewhelp->myErrorViewer($errors, $this->getOptions()); Here I'm telling the decorator to use the My_Form_Error_View_Helper view helper, which in turn look something like this:

class My_Form_Error_View_Helper extends Zend_View_Helper_FormElement
{
    public function myErrorViewer($errors, array $options = null)
    {

        if (empty($options['class'])) {
            $options['class'] = 'errors';
        }

        $start = "<span%s>";
        $end = "</br></span>";
        if (strstr($start, '%s')) {
            $start   = sprintf($start, " class='{$options['class']}'");
        }

        $html  = $start
               . array_pop($errors)
               . $end;

        return $html;
    }
}

Again I borrow most of this function from the original FormErrors View Helper. This is by no means the solution you should implement, but hopefully this sets you on the right path on how you can use decorators and view helper to customize the output of your form. I recommend the following two reads about Decorators and View Helpers (They are a huge topic by themselves)

Decorators View Helpers