避免Symfony强制显示表单域

时间:2014-08-20 07:41:40

标签: forms symfony

我有一个表单类型,设置10个字段。 在我的树枝模板中,我每次显示8个字段,条件中包含2个字段:

{% if computed is not empty %}
    <div class="container-filters">
        <div class="form-group">
             {{ form_row(form.filterStart) }}
        </div>
        <div class="form-group">
              {{ form_row(form.filterEnd) }}
        </div>
        <input type="submit" name="submit" class="btn btn-evo" value="OK" />
    </div>
{% endif %}

但无论我的条件是真还是假,Symfony都会显示这两个字段。如果我的条件为真,则会因为我的{{form_row()}}语句而显示它们,这是正常行为。如果我的条件为假,则无论如何都会显示它们,因为Symfony 2会强制显示表单字段。

如何防止这种奇怪的行为?

3 个答案:

答案 0 :(得分:32)

我猜你的代码后面有一个form_end或form_rest。

您可以告诉不要在form_end帮助器中渲染剩余的字段:

{# don't render unrendered fields #}
{{ form_end(form, {'render_rest': false}) }}

http://symfony.com/doc/current/reference/forms/twig_reference.html

顺便说一句,我建议你在FormType中添加你的逻辑。

答案 1 :(得分:8)

您可以强制将项目渲染为..

{% do form.filterStart.setRendered %}
{% do form.filterEnd.setRendered %}

如果您使用的是{{ form_end(form, {'render_rest': false}) }},那么您应该知道需要渲染CSRF令牌,除非您专门将其关闭。

这两种方法都可能会清除模型上的值,因为它们不在发布的数据中。

或者你可以把字段放在一个隐藏的div中,但这有点hacky(然后其他方式也是如此)。

正如Christophe所提到的,最好的方法是将其添加到您的表单逻辑中。 您选择这样做的方式取决于这些字段的可用性是取决于预定因素还是来自实际模型的数据。

<强>预定

您的表单类型

class YourFormType extends AbstractType
{
    //...

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        //...

        if ($options['your_condition']) {
            $builder
                ->add('filterStart', 'date')
                ->add('filterEnd', 'date')
            ;
        }
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            //...
            'your_condition' => false,
        ));
    }

    //...
}

创建表单

$form = $formFactory->create(
        // Or $this->createForm if you are using the controller
    'your_form_name', 
    $model, 
    array('your_condition' => true/false)
);

来自模特

表格类型

class YourFormType extends AbstractType
{
    //...

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        //...

        $builder
            ->addEventListener(FormEvents::PRE_SET_DATA, function(FormEvent $event) {
                $form = $event->getForm();
                $model = $event->getData();

                if (!$model || 'something' !== $model->getSomething()) {
                    return;
                }

                $form
                    ->add('filterStart', 'date')
                    ->add('filterEnd', 'date')
                ;
            })
        ;
    }

    //...
}

然后,在您的模板中渲染这些字段时,需要您检查字段是否已创建,例如..

{% if form.filterStart is defined and form.filterEnd is defiend %}
    <div class="container-filters">
        <div class="form-group">
            {{ form_row(form.filterStart) }}
        </div>
        <div class="form-group">
            {{ form_row(form.filterEnd) }}
        </div>
        <input type="submit" name="submit" class="btn btn-evo" value="OK" />
    </div>
{% endif %}

答案 2 :(得分:0)

由于FormView->children具有公共访问权限,您可以在控制器中处理逻辑:

if(<condition>) {
    $formView->children['filterStart']->setRendered();
    $formView->children['filterEnd']->setRendered();
}