jurian sluiman

{
Wissel naar

Hide hidden Zend_Form elements

The Zend_Form has support for hidden elements, Zend_Form_Element_Hidden. In default setup they are rendered in a <dt><dd> wrapper and this can raise some problems when applying styles to the form.

This blog article suggests a new idea to solve this problem. On the Internet many proposals are posted with all some drawbacks, which are solved in this idea.

By default a hidden element is rendered like this:

<dt><label for="element"></label></dt>
<dd><input type="hidden" name="element" id="element"></dd>

In this case the <dt> is empty but occupies some space which you can't remove by applying css rules. Therefore you'd like to add, for example, a class to the <dt> so you can apply a display:none.

Most methods use the Zend_Form::render() method in which they loop through all elements and grab the elements of the type Zend_Form_Element_Hidden. One example is the suggestion of Tudor Barbu. There are two drawbacks of this example:

  1. You cannot reach the elements inside subforms
  2. You loop through all form elements, which is a huge performance impact

What then?

The case is actually quite simple. Instead of using the Zend_Form::render(), you apply only the class to the hidden elements itself. The Zend_Form_Element_Hidden extends the Zend_Form_Element, so Zend_Form_Element_Hidden uses also the (general) Zend_Form_Element::loadDefaultDecorators() method. When we create our own My_Form_Element_Hidden class, overriding the loadDefaultDecorators() method we can add some additional features to the default decorators.

<?php
class My_Form_Element_Hidden extends Zend_Form_Element_Hidden
{
    /**
     * Load default decorators
     *
     * @return void
     */
    public function loadDefaultDecorators()
    {
        if ($this->loadDefaultDecoratorsIsDisabled()) {
            return;
        }

        $decorators = $this->getDecorators();
        if (empty($decorators)) {
            $this->addDecorator('ViewHelper')
                ->addDecorator('Errors')
                ->addDecorator('Description', array('tag' => 'p', 'class' => 'description'))
                ->addDecorator('HtmlTag', array('tag' => 'dd',
                                                'id'  => $this->getName() . '-element'))
                ->addDecorator('Label', array('tag' => 'dt',
                                              'class' => 'hidden'));
        }
    }
}

The only change made here is the added parameter 'class' => 'hidden' to the label. Now the <dt> gets a class hidden.

The last question is how we can initiate the My_Form_Element_Hidden instead of the Zend_Form_Element_Hidden. Zend_Form uses the elements by loading them like plugins. If we add our custom prefixPath to the form, Zend_Form will look into that path first and find our My_Form_Element_Hidden first. Other elements (like My_Form_Element_Text) are not found and the Zend_Form_Element_* classes will be loaded.

<?php
class My_Form extends Zend_Form
{
    public function __construct ($options = null)
    {
        $this->addPrefixPath('My_Form_', 'My/Form/');
        parent::__construct($options);
    }
}

Now we're finished. We have a file library/My/Form.php to load the hidden element automatically from our namespace. We also have a library/My/Form/Element/Hidden.php to adjust the default decorators. We end up with this html and can apply a css rule to hide the <dt> line.

If you create your form, keep in mind you don't need to extend the Zend_Form but your own My_Form. Then all hidden elements are hidden automatically (if the correct css is loaded), because the html is now like this:

<dt class="hidden"><label for="element"></label></dt>
<dd><input type="hidden" name="element" id="element"></dd>

Comments

There are no comments yet. Be the first to place one!

Place a comment

If you have a user account for this site, you can login to click here.

Please note your comment below will be removed if you login!

 
 

The address is stored internally but not displayed on this site. We will respect your privacy.

In your message no html is allowd. A blank line creates a new paragraph, an url gets a hyperlink.