在嵌套子表单上使用ViewScript Decorator(Zend表单)

时间:2011-09-28 21:07:58

标签: zend-framework zend-form zend-form-sub-form

我想使用视图脚本来渲染我的zend表单,因为它似乎是最好的方法 在使用Zend_Elements类的同时控制表单的布局/设计。

从视图脚本中,我使用$this->element->getElement('elementName')渲染元素。

我遇到了元素名称的问题。这实际上是表单内子表单内的子表单。

当我使用FormElements装饰器时,元素的完全限定名称是[subForm] [subForm] [element],这很好。 我转移到viewScript装饰器,它改为subForm [subForm] [element]。

我明白我需要使用PrepareElements装饰器来解决这个问题,但这导致名称改变形式[subForm] [form] [subForm] [subForm] [elements](它在开头的前两个名称翻了一番)。

我应该如何处理这个问题?

感谢。

更新:我尝试调试PrepareElements,我真的不明白在做什么。 看起来它在第一次迭代中工作正常,但是当在其中一个中间子表单上运行时,它再次添​​加了表单[subform]前缀。

当我没有使用PrepareElements装饰器时,我只是在名称中缺少“form”前缀(即,而不是形式[subForm] [element],我只得到subForm [element])。

可能我可以解决这个问题吗?

我尝试更改belongsTo,但只替换了“subForm”前缀。

实际上看起来缺少的是subForm上的belongsTo方法。

同样,这完全是因为ViewScript装饰器。它适用于FormElements装饰器。

更新2:为了澄清,我不介意更改此名称,但是当我调用form-> populate时,它会导致我的字段无法填充。

编辑:我认为我已经将问题缩小到了这个问题:当我在setDefaults中获取我的值时,它们的排序如下:

array(
\"formElements1-name\" => value1... \"subFormName\" => array(
\"parentFormName\" => array(
\"subFormName\" => subForm-values-array
)
)

... 这里的主要问题是"parentFormName" => "subFormNAme"..它会重演什么?我已经处于主要形式。我猜这是因为我设置了setElementsBelongTo(formName[subFormName]),但如果我不这样做,那么我会将我的子表单值与表单完全分开,

即。     values array = array(     \“formName \”=>阵列(     formValues     ),“subFormNAme \”=>阵列(     subFormValues     )

,而我将其视为

array(
formName => array(
subFormNAme => values-array
)
)...

甚至可以使这项工作吗?

4 个答案:

答案 0 :(得分:8)

您是否只是尝试使用视图脚本中的<?php echo $this->form; ?>输出表单?

这适用于简单的表单,但对于我更复杂的表单,我倾向于单独呈现每个元素,但不需要在每个单独的元素上使用ViewScript装饰器来执行此操作。只需从您的视图脚本中尝试这样的事情:

<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>

这就是我做大多数表格的原因,因为我希望有一些元素占据宽度的一半而其他元素占据整个宽度。

令人惊讶的是,参考指南并未告诉您可以执行此操作。我似乎在过去记得有关它的页面但现在找不到它。当我开始使用Zend Framework时,我认为唯一可以让我的表单输出我想要的方式就是创建复杂的装饰器,但事实并非如此。

Matthew Weier O'Phinney在rendering Zend_Form decorators individually上发表了一篇很棒的博文,解释了我上面所做的事情。我希望他们把这个添加到Zend Form的第一页,因为这对我来说是令人沮丧的。事实是,90%的表单单独呈现元素,而不是仅仅回显表单本身。

注意:要阻止ZF将表单元素包含在dt和dd标记中,我将此装饰器应用于所有标准表单元素。我有一个基本表单类,我扩展了所有表单,所以我不必在任何地方重复这个。这是元素的装饰器,所以我可以使用标签来封闭我的元素。

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' => '*'))
);

对于我的提交按钮,我使用

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

答案 1 :(得分:2)

当前的解决方案是在子表单上使用PrepareElements装饰器进行一次更改 - 删除PrepareElements代码中的递归调用。此外,不需要“setElementsBelongTo”。

这似乎生成了正确的名称和ID。

答案 2 :(得分:0)

解决方案是使用belongsTo()表单元素属性 示例:

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

这样,render()方法将使用表单元素名称,如

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

答案 3 :(得分:0)

我有同样的问题,我用装饰器解决了它

1:使用元素

创建通用子表单

2:使用具有PrepareElements的特定装饰器

3:使用setIsArray(true)将表单更改为数组

示例:

表格

$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);

装饰

<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>

享受

抱歉我的英文,我是法国人