Using ViewScript Decorator on Nested Subforms (Zend Form)

≡放荡痞女 提交于 2019-11-27 08:58:52

Are you just trying to output your form using <?php echo $this->form; ?> from your view script?

That works well for simple forms, but for my more complex forms I tend to render each element individually but don't need to use ViewScript decorator on each individual element to do this. Just try something like this from your view script:

<div class="form">
    <fieldset>
        <legend>Some Form Name</legend>
        <form action="<?php echo $this->escape($this->form->getAction()) ?>"
              method="<?php echo $this->escape($this->form->getMethod()) ?>"
              enctype="multipart/form-data">

            <?php echo $this->form->id; // render the id element here ?>

            <div class="half">
                <?php echo $this->form->name; // render the user name field here ?>
            </div>
            <div class="half">
                <?php echo $this->form->description; // render the description element here ?>
            </div>
            <div class="clear"></div>

            <div class="half">
                <?php echo $this->form->address1; // render the address ?>
            </div>
            <div class="half">
                <?php echo $this->form->address2; // render address2 ?>
            </div>
            <div class="clear"></div>

            <div class="third">
                <?php echo $this->form->zip; // render zip code ?>
            </div>
            <div class="third">
                <?php echo $this->form->city; // render city ?>
            </div>
            <div class="third">
                <?php echo $this->form->state; // render state ?>
            </div>
            <div class="clear"></div>

            <div class="half">
                <?php echo $this->form->country; // render country ?>
            </div>
            <div class="clear"></div>

            <?php echo $this->form->submit; ?>

        </form>
    </fieldset>
</div>

That is how I do most of my forms because I want to have some elements take up half the width and others the full width.

Surprisingly, the reference guide doesn't tell you that you can do this. I seem to remember a page about it in the past but cannot find it now. When I got started with Zend Framework, I thought the only way I could get my form to output exactly how I wanted was to create complex decorators, but that is not the case.

Matthew Weier O'Phinney has a great blog post on rendering Zend_Form decorators individually which explains what I did above. I hope they add this to the first page of Zend Form because that was discouraging to me at first. The fact is, 90% of my forms render elements individually instead of just echo'ing the form itself.

Note: To stop ZF from enclosing my form elements in the dt and dd tags, I apply this decorator to all of my standard form elements. I have a base form class that I extend all of my forms from so I don't have to repeat this everywhere. This is the decorator for the element so I can use tags to enclose my elements.

public $elementDecorators = array(
    'ViewHelper',
    'Errors',
    array('Description', array('tag' => 'p',    'class' => 'description')),
    array('HtmlTag',     array('tag' => 'div', 'class' => 'form-div')),
    array('Label',       array('class' => 'form-label', 'requiredSuffix' => '*'))
);

For my submit buttons I use

public $buttonDecorators = array(
    'ViewHelper',
    array('HtmlTag', array('tag' => 'div', 'class' => 'form-button'))
);

The current solution is to use the PrepareElements decorator on the subforms with one change - remove the recursive call in the PrepareElements code. Also, no "setElementsBelongTo" is required.

This seem to generate the correct names and ids.

Eureka

The solution would be to use the belongsTo() form element property.
Example :

new Zend_Form_Element_Text('<elementName>', array('belongsTo' => '<subformName>'))

In this way, the render() method will use a form element name like

name="<subformName>[<elementName>]"

I had the same problem and i solved it with a decorator

1 : Create a generic subform with elements

2 : Using a specific decorator with PrepareElements

3 : Change form to an array with setIsArray(true)

Example :

Form

$i = 4;
for($i = 0; $i < $nbReclam ; $i++)
{
    $rowForm = new Zend_Form_SubForm($i);
    $name= new Zend_Form_Element_Textarea('name');
    $rowForm->addElement($name);
    $this->addSubForm($rowForm, $i);
}

$this->setDecorators(array(
            'PrepareElements',
            array('ViewScript', array('viewScript' => 'myDecorator.phtml')),
    ));   


$this->setIsArray(true);

Decorator

<table>
<thead>
    <tr>
        <th>N°</th>
        <th>Name</th>
    </tr>
</thead>
<tbody>
    <?php foreach ($this->element->getSubForms() as $subForm) : ?>
            <tr>
               <td> <?php echo $i++?> </td>
               <?php foreach ($subForm->getElements() as $row) : ?>
                   <td><?php echo $row ?></td>
               <?php endforeach ?>
            </tr>
        <?php endforeach ?>
    </tbody>
</table>

Enjoy

Sorry for my english, i am french

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!