更新答案
让我们假设一个控制器方法 - 我定义了两种形式 edit_form 和 delete_form。不要太担心这些,它们只是概念的证明。这里重要的是我有两个表单要发送到要渲染的模板:
// Foo\BarBundle\Controller\BazController
public function editAction()
{
// a placeholder 'edit' form
$editForm = $this->createFormBuilder()
->add('name', 'text')
->add('email', 'email')
->add('send', 'submit')
->getForm();
// a placeholder 'delete' form
$deleteForm = $this->createFormBuilder(['id' => 1])
->add('id', 'hidden')
->getForm();
// assign form views to template
return [
'edit_form' => $editForm->createView(),
'delete_form' => $deleteForm->createView(),
];
}
接下来是模板。我们有两种形式要渲染:edit_form 和 delete_form。我们需要考虑几个问题 - 不允许在表单中呈现表单,因此我们不能在 edit_form 中呈现 delete_form,反之亦然。
但是,正如我在下面解释的那样,我们可以使用 HTML5 form 属性将表单元素放置在 <form> 上下文之外,并且仍然将它们链接到该表单(具有上述 IE* 限制)。因此,让我们这样做,并在适当的时候提出解决方法。
最少侵入性的做法是在edit_form 之后渲染delete_form,但将edit_form 删除按钮放在edit_form 内部。
我不知道您是否使用 CSS 框架来帮助您进行布局 - 我假设 Bootstrap 2.* 在这里您可能需要更新您的标记 - 无论哪种方式,这个想法都应该足够清晰:
<div class="row">
{{ form_start(edit_form, {'attr': {'id': 'edit-form'}}) }}
<div class="span4">
<ul class="record_actions">
<li>{{ form_widget(edit_form.send)}}</li>
<li><button id="delete-form-submit" form="delete-form">
Delete
</button>
</li>
</ul>
</div>
<div class="span4">
{{ form_rest(edit_form) }}
</div>
{{ form_end(edit_form) }}
</div>
{{ form(delete_form, {'attr': {'id': 'delete-form'}, 'method': 'GET'}) }}
上面的 HTML 产生了一个类似于下面的布局:
几点说明:
-
我为表单创建了一个两列布局。 .record_actions 按钮呈现在左列 - 这是必不可少的 - 但在这种情况下,它们使用 Bootstrap 的 .pull-right 向右浮动。
更新按钮:我要做的第一件事是将submit 按钮呈现在我想要的ul.record_actions 中:<li>{{ form_widget(edit_form.send)}}</li>
删除按钮:我没有在delete_form 上定义submit 按钮,因为我想在delete_form 的上下文之外显式创建它,而不是放置它我在哪里。请注意,我在此元素上定义了一个名为 delete-form 的表单属性。这会将这个元素链接到delete_form 而不是edit_form:<li><button id="delete-form-submit" form="delete-form">Delete</button></li>
剩余字段:根据 @Kix 的建议,在第二列中,我可以使用 {{ form_rest(edit_form) }} 隐式转储所有剩余的 edit_form 字段!
删除表单最后,我们将delete_form 在edit_form 之外 渲染为{{ form(delete_form, {'attr': {'id': 'delete-form'}, 'method': 'GET'}) }}。这里有几点需要注意——我们明确地为带有{'attr': {'id': 'delete-form'} 的表单添加了一个id。这很重要,因为它是删除按钮所引用的属性。在这种情况下,我还添加了'method': 'GET' 以在我的机器上进行测试。您可能希望忽略它(在这种情况下,它默认为 POST)
你有它......这应该可以帮助你定义你的首选布局。
但是,我们仍然需要解决 IE。如果您使用的是 jQuery,您可以向删除按钮添加一个单击处理程序,我们已为其分配了 ID #delete-form-submit。请注意,以下是建议,未经测试:
$(function() {
if ($.browser.msie) { // @see: http://api.jquery.com/jquery.browser/
$('#delete-form-submit').on('click', function(e) {
e.preventDefault();
$('#delete-form').submit();
});
});
});
现在您需要担心禁用 JS 的 IE 用户...与否! ;) 希望这会有所帮助。
原答案
我认为您的问题可能与 Symfony 无关...让我解释一下:
您是否使用表单构建器创建表单的submit 按钮?我假设是这样,因为您没有在上面粘贴的 twig sn-p 中明确创建一个。
当然,这完全没问题。我通常只是像这样定义我的 Twig 表单模板,我认为这是较旧的方法(因为 2.4 文档似乎没有建议以下内容):
<form class="form-horizontal" action="{{ path('foo_edit') }}" method="post" {{ form_enctype(edit_form) }}>
{{ form_widget(edit_form) }}
<input type="submit">
</form>
这种方式在我看来是完全可以接受的——你只是没有定义submit按钮。
当然这并不能解决你的问题,因为你要“突围”出表格。但是您实际上可以使用带有form 属性的HTML5 来做到这一点,它允许您将不同的标签链接到特定的标签。一个通用的例子:
<form id="foo">
<label>Username</label>
<input type="text" name="username">
</form>
<ul>
<li><input type="submit" form="foo">
</ul>
注意submit 按钮在form#foo 之外,但form 属性仍然链接到它。
显然,它的用处仅限于您想要支持的浏览器范围,因为它是 HTML5 功能。
编辑
我检查过 - 它有相当广泛的浏览器支持,除了.... drumroll IE。显然包括IE10。不幸的是,我认为这会破坏交易。
kix 的上述方法可以很好地工作,但是,打印出您明确需要的单个表单小部件,然后使用 form_rest。我要补充一点,并说它可能不完全适用于您上面的 HTML 布局 - iirc 您必须在调用form_rest 之前明确打印出任何字段。