Symfony2表单:如何在同一视图中两次呈现相同的元素

时间:2013-02-04 08:23:22

标签: php symfony twig

我有一个控制器,我在其中创建一个表格,里面有两个下拉列表。

当我渲染视图时,我希望在页面的顶部和底部具有相同的表单元素。问题是表单elemet(下拉列表)仅显示在页面顶部,即使我要求twig将它们也放在底部。

以下是我想要的内容:

enter image description here

1和2是下拉列表。我想在页面的顶部和底部复制它。

关于如何做到的任何想法?

顶部内容和底部内容,其中两个下拉列表位于单个sseparate twig文件(searchPanel.html.twig)中,此文件包含在页面中

{% include "MyBundle:Search:searchPanel.html.twig" %}

这是searchPanel.html.twig

<div class="searchPanel">

<form action="{{ path }}" method="POST" {{ form_enctype(form) }}>
    Papers per page
    {{ form_widget(form.papers_per_page, { 'class': 'ppp'}) }}

    / Sort by 
    {{ form_widget(form.sort_by, { 'class': 'sort'}) }}
    {{ form_rest(form) }}

    / Papers ({{ papers_number }} results)

 <input type="submit" class="updateSearchResults" value="Update"></input>
</form>

3 个答案:

答案 0 :(得分:5)

您的方法中的一个问题是,Symfony的Form-component将呈现带有id的表单元素,如果您在页面上呈现两次相同的表单,则会复制该表单元素。您也可能遇到csrf_token问题。形式的要点不是要复制的。

这是我要做的。在不使用Symfony \ Form的情况下创建包含您的paginator表单的twig-template,即静态创建所有表单元素并将其传递给paginator-object(或数组)以获取数据而不是使用form_widget()。像这样:

<form action="{{ path(app.request.attributes.get('_route') }}" method="POST">
    <select name="paginator[per_page]">
        {% for per_page in paginator.papers_per_page %}
        <option value=""{{ per_page }}">{{ per_page }}</option>
        {% endfor %}
    </select>
</form>

表单操作会自动将数据提交到当前路由,因此您可以将其嵌入到不同的操作中,并将数据提交给同一操作。在POST时,您可以使用post-data创建一个paginator-object,然后将其添加为表单的数据。之后你就像往常一样使用isValid()。

在您的控制器中,您可以获得如下数据:

use Symfony\Component\HttpFoundation\Request;
// ...

public function PaperController()
{
    public function listAction(Request $request)
    {
        if ($request->getMethod() == 'POST') {
            $data = $request->request->get('paginator');
            $paginator = new Paginator($data);

            $form = new PaginatorFormType();
            $form->setData($paginator);

            if ($form->isValid()) {
                // ...
            }
        }
    }
}

您可以轻松地在您的视图中嵌入表单,如下所示:

{{ include 'AcmeDemoBundle:Form:paginator.html.twig' with { 'paginator': paginator } }}

基本上,您只需使用控制器中的Form-component进行验证。如果您想设置一些默认值或添加其他参数,您可能希望从该模板创建macro,但对于您的用例,这应该足够了。也许其他人有更好的解决方案,但这就是我在我的一个项目中遇到类似问题的方式。

答案 1 :(得分:2)

另一个选项是用户渲染树枝助手。这种方式可以在页面中呈现相同的表单,并且可以根据需要多次显示。区别在于使用此帮助程序,还需要将表单呈现视为独立控制器Action,即: 在您的twig模板中的每个位置,您希望在帮助器中呈现表单以调用表单,其中必须是这样的:

{{ render(controller('BundleNameBundle:Controller:Action', {
    'param': paramId
})) }}

此后只是创建控制器......

答案 2 :(得分:0)

另一个选项是在控制器中创建2个表单:

 //first form
 $form = $this->createForm(new MyFormType(), ...);

 //second form: must have different form name that default,
 //to render in twig the fields with different ids
 $formType = new MyFormType();
 $formType->setName('second_form_name');
 $formSecond = $this->createForm($formType, ...);

渲染树枝形式时发送两者:

return $this->render( ... 
            'form' => $form->createView(), 'formSecond'=>$formSecond->createView()));

然后定义名称为

的第二个
  

formSecond

,它会与第一个冲突。