首页 > 解决方案 > 如何使 Twig 模板正确显示精美的 Bootstrap 3 单选按钮?

问题描述

我正在运行 Symfony 4.2 并尝试创建两个 Bootstrap 3 单选按钮。这是我要创建的 HTML:

<div class="btn-group btn-group-justified" data-toggle="buttons">
    <label class="btn btn-lg btn-default">
        <input type="radio" name="inquiry[flexDates]" value="yes">YES
    </label>
    <label class="btn btn-lg btn-default">
        <input type="radio" name="inquiry[flexDates]" value="no">NO
    </label>
</div>

这是我的表单构建器代码:

$builder
    ->add('flexDates', ChoiceType::class, [
        'choices' => [
            'Yes' => 'yes',
            'No'  => 'no',
         ],
         'placeholder' => false,
         'required' => false,
         'empty_data' => '',
         'expanded' => true,  // these two options (expanded = true and
         'multiple' => false, // multiple = false) make it a radio button
     ])

我安装了 Bootstrap 3 主题 ( )并bootstrap_3_layout.html.twig尝试了 和 的各种form_row()组合。我已经设置了几种不同的方式,但我无法弄清楚如何生成上面的 HTML。似乎总是有额外的 s 或 HTML 导致它显示不正确。form_label()form_widget()attrlabel_attr<div>

HTML 是一直运行良好的硬编码表单的一部分,我正在尝试将其转换为 Twig 模板。转换所有其他字段很简单,但我浪费了将近一天的时间来尝试复制单选按钮。

看起来应该很容易,但是从我能找到的任何文档或示例中都不清楚如何做到这一点。

我尝试创建自己的块小部件,但我不知道如何制作<label>包含<input>(而不是之前或之后)。为了使事情起作用,标签必须环绕输入。

文件中有一个接近我需要的{% block checkbox_radio_label %}定义bootstrap_3_layout.html.twig,但我无法让它工作。它使用,但是当我尝试使用它时{{ widget|raw }},Symfony 给了我一个错误。variable "widget" does not exist

到目前为止,https://symfony.com/doc/current/form/form_customization.html上的信息更令人困惑而不是有用。我多年来一直在使用 Twig,并且几乎可以做任何其他事情,但是这个问题让我很难过。我知道我可以编写自己的自定义过滤器,但似乎应该有更简单的方法。

更新:我能够使用这个去除多余标签的丑陋黑客来使事情正常进行:

 {% filter replace({
     '<div class="radio"><label':'<label',
     '</label></div>':'</label>',
     '<div id="inquiry_flexDates">':'',
     '</label></div>':'</label>',
     '</div>':'',
   })|raw %}
   {{ form_widget(form.flexDates, {label_attr:{class: 'btn btn-lg btn-default'}}) }}
{% endfilter %}

它现在正在工作,但必须有更好的方法......

标签: symfonytwig

解决方案


表单类型特别讨厌,因为它在ChoiceType后台做了很多事情(与大多数其他“基本”表单类型相比)。它以某种方式将选择转换为自己的表单元素,具体取决于扩展和多个选项。它的表单渲染也相当混乱/复杂,我花了一些时间重写,最后我创建了一个新的表单类型,只是为了我的不同渲染(因为老实说我不知道​​如何管理block_prefix选项)。

use Symfony\Component\Form\Extension\Core\Type\ChoiceType;

class MychoiceType extends ChoiceType {
   function getBlockPrefix() {
       return 'mychoice';
   }
   // find a way to set the expanded option of the ChoiceType 
   // fixed to true
}

在您的表单样式中(我怀疑您知道如何创建一个),您会生成一个新的小部件和标签。我现在找不到我的代码,但希望以下内容能在某种程度上重现我曾经做过的事情......绝对可能有一种更优雅的方式,实际上覆盖了 bootstrap3 的表单主题,但是......好吧:

{% block mychoice_label %}
   {{ parent() }}
{% endblock mychoice_label %}

{% block mychoice_widget %}
   <div class="btn-group btn-group-justified" data-toggle="buttons">
   {% for child in form.children %}
       {# see checkbox_radio_label for more generic version #}
       <label class="btn btn-lg btn-default">
           <input type="radio" name="{{ id }}" value="{{ child.value }}">{{ child.label }}
       </label>
   {% endfor %}
   </div>
{% endblock mychoice_widget %}

这是选择类型的一个非常具体的版本,为了也支持多个,您当然可以扩展小部件以支持它。但我希望这将为您指明正确的方向。我不确定是否必须将小部件代码包装在某些东西中以适应特定的表单主题,但我想你也会弄明白的;o)

您可能必须为子表单元素设置渲染标志。不太确定。


推荐阅读