Issues

ZF-11517: unwanted Label decorator gets added when creating Form from Config object

Issue Type: Bug Created: 2011-06-30T09:42:51.000+0000 Last Updated: 2012-11-07T20:48:15.000+0000 Status: Resolved Fix version(s): - 1.12.1 (18/Dec/12)

Reporter: Matthieu Larcher (mattso) Assignee: Frank Brückner (frosch) Tags: - Zend_Form

  • FixForZF1.12.1
  • zf-crteam-priority

Related issues: - ZF-10065

Attachments: - Radio.php.patch

Description

Here is the scenario :

You create an array describing the form, listing the decorators you want to associate to your element. You create a Zend Config object from this array. You create a Zend Form from the Zend Config object.

At this point, your form element holds the decorators you assigned it, plus a Label decorator.

here's some testcase code :

<pre class="highlight">
$options = array('1' => 'answer1',
                 '2' => 'answer2',
                );

$elements['element_3'] = array('type'    => 'radio',
                               'options' => array(
                                   'required'     => true,
                                   'multiOptions' => $options,
                                   'decorators'   => array(
    'ViewHelper',
    'Errors',
    array(array('wrapper' => 'HtmlTag'), array('tag'   => 'div',
                                               'class' => 'content',
                                               )),
    array(array('Fieldset' => 'HtmlTag'), array('tag'      => 'fieldset',
                                                'data-role' => 'controlgroup',
                                                )),
    )
                                                       ),
                                                   );

$elements['formSubmit'] = array('type'    => 'submit',
                                'options' => array('label'      => 'valider',
                                                   'decorators' => array(
                                        'ViewHelper',
                                        'Errors'
                                    )
                                                )
                                );

$configArray = array('elements'          => $elements,'decorators'        => array('FormElements',
                                                  array('HtmlTag', array('tag' => 'div')),
                                                  'Form')
                     );

$config = new \Zend_Config($configArray);
$form   = new \Zend_Form($config);
var_dump($form);die();

I noticed this on the Radio element, it might be the case with other elements too.

You can prevent this behaviour by explicitely setting disableLoadDefaultDecorators to true on your element in the config array/config object.

Comments

Posted by Kai Uwe (kaiuwe) on 2011-06-30T10:38:12.000+0000

Zend_Config removed as affected components

Posted by Kai Uwe (kaiuwe) on 2011-06-30T10:48:34.000+0000

This is the normal behavior:

<pre class="highlight">
/**
 * Load default decorators
 *
 * Disables "for" attribute of label if label decorator enabled.
 *
 * @return Zend_Form_Element_Radio
 */
public function loadDefaultDecorators()
{
    if ($this->loadDefaultDecoratorsIsDisabled()) {
        return $this;
    }
    parent::loadDefaultDecorators();
    $this->addDecorator('Label', array('tag' => 'dt',
                                       'disableFor' => true));
    return $this;
}

I see no problem and the solution have you already given.

<pre class="highlight">
$elements['element_3'] = array(
    'type'    => 'radio',
    'options' => array(
        'required'     => true,
        'multiOptions' => $options,
        'decorators' => array(
            'ViewHelper',
            'Errors',
            array(
                array(
                    'wrapper' => 'HtmlTag',
                ),
                array(
                    'tag'   => 'div',
                    'class' => 'content',
                ),
            ),
            array(
                array(
                    'Fieldset' => 'HtmlTag',
                ),
                array(
                    'tag'       => 'fieldset',
                    'data-role' => 'controlgroup',
                ),
            ),
        ),
        'disableLoadDefaultDecorators' => true,
    ),
);

Posted by Matthieu Larcher (mattso) on 2011-06-30T11:07:46.000+0000

This is not the exptected behaviour. When you manually declare a set of decorators on your form element, the usual behaviour is to automatically disable default decorators. For example when you use $element->setDecorators(array(...)), you don't get any default decorators added.

Posted by Kai Uwe (kaiuwe) on 2011-06-30T11:30:33.000+0000

Hi Matthieu, I know what you mean. Here is an example for a fix:

<pre class="highlight">
public function loadDefaultDecorators()
{
    if ($this->loadDefaultDecoratorsIsDisabled()) {
        return $this;
    }
    parent::loadDefaultDecorators();
            
    $labelDecorator = $this->getDecorator('Label');        
    if (false !== $labelDecorator) {
        $labelDecorator->setOption('disableFor', true);
    }
    
    return $this;
}

Posted by Matthieu Larcher (mattso) on 2011-06-30T11:44:55.000+0000

Kai, Thanks for you proposal, I guess it would do the trick. On the other hand, wouldn't it be more appropriate just not to go through the loadDefaultDecorators method when decorators have been defined ?

Posted by Kai Uwe (kaiuwe) on 2011-06-30T11:56:08.000+0000

See the parent method:

<pre class="highlight">
/**
 * Load default decorators
 *
 * @return Zend_Form_Element
 */
public function loadDefaultDecorators()
{
    if ($this->loadDefaultDecoratorsIsDisabled()) {
        return $this;
    }

    $decorators = $this->getDecorators();
    if (empty($decorators)) {
        $getId = create_function('$decorator',
                                 'return $decorator->getElement()->getId()
                                         . "-element";');
        $this->addDecorator('ViewHelper')
             ->addDecorator('Errors')
             ->addDecorator('Description', array('tag' => 'p', 'class' => 'description'))
             ->addDecorator('HtmlTag', array('tag' => 'dd',
                                             'id'  => array('callback' => $getId)))
             ->addDecorator('Label', array('tag' => 'dt'));
    }
    return $this;
}

Posted by Kai Uwe (kaiuwe) on 2011-06-30T15:02:48.000+0000

My solution does not work because it breaks a test:

<pre class="highlight">
/**
 * @group ZF-9682
 */
public function testCustomLabelDecorator()
{
    $form = new Zend_Form();
    $form->addElementPrefixPath('My_Decorator', dirname(__FILE__) . '/../_files/decorators/', 'decorator');

    $form->addElement($this->element);

    $element = $form->getElement('foo');

    $this->assertType('My_Decorator_Label', $element->getDecorator('Label'));
}

ZF-9682

Posted by Kai Uwe (kaiuwe) on 2011-06-30T15:19:25.000+0000

An unit test:

<pre class="highlight">
/**
 * @group ZF-11517
 */
public function testRenderingWithIndividualDecoratorsAsConstructorOptionsWithoutLabel()
{
    $element = new Zend_Form_Element_Radio(array(
        'name'         => 'foo',
        'multiOptions' => array(
            'bar'  => 'Bar',
            'baz'  => 'Baz',
        ),
        'decorators' => array(
            'ViewHelper',
            'Errors',
            array(
                array(
                    'wrapper' => 'HtmlTag',
                ),
                array(
                    'tag' => 'div',
                ),
            ),
            array(
                array(
                    'fieldset' => 'HtmlTag',
                ),
                array(
                    'tag' => 'fieldset',
                ),
            ),
        ),
    ));

    $this->assertFalse($element->getDecorator('Label'));

    $html = $element->render($this->getView());
    $this->assertNotContains(' ', $html);
}

Posted by Kai Uwe (kaiuwe) on 2011-06-30T15:21:51.000+0000

Proposal 1:

<pre class="highlight">
/**
 * Load default decorators
 *
 * Disables "for" attribute of label if label decorator enabled.
 *
 * @return Zend_Form_Element_Radio
 */
public function loadDefaultDecorators()
{
    if ($this->loadDefaultDecoratorsIsDisabled()) {
        return $this;
    }

    $decorators = $this->getDecorators();
    if (empty($decorators)) {
        $getId = create_function('$decorator',
                                 'return $decorator->getElement()->getId()
                                         . "-element";');
        $this->addDecorator('ViewHelper')
             ->addDecorator('Errors')
             ->addDecorator('Description', array('tag' => 'p', 'class' => 'description'))
             ->addDecorator('HtmlTag', array('tag' => 'dd',
                                             'id'  => array('callback' => $getId)))
             ->addDecorator('Label', array('tag' => 'dt', 'disableFor' => true));
    }
    return $this;
}

Proposal 2:

<pre class="highlight">
/**
 * Load default decorators
 *
 * Disables "for" attribute of label if label decorator enabled.
 *
 * @return Zend_Form_Element_Radio
 */
public function loadDefaultDecorators()
{
    if ($this->loadDefaultDecoratorsIsDisabled()) {
        return $this;
    }

    parent::loadDefaultDecorators();

    if (isset($this->_decorators['Label'])
        && !isset($this->_decorators['Label']['options']['disableFor']))
    {
         $this->_decorators['Label']['options']['disableFor'] = true;
    }

    return $this;
}

Posted by Frank Brückner (frosch) on 2012-05-04T15:25:32.000+0000

Patch and unit tests added.

Posted by Rob Allen (rob) on 2012-11-07T20:48:15.000+0000

Patch applied to trunk (25108) and release-1.12 (25109)

Have you found an issue?

See the Overview section for more details.

Copyright

© 2006-2016 by Zend, a Rogue Wave Company. Made with by awesome contributors.

This website is built using zend-expressive and it runs on PHP 7.

Contacts