如何使Twig模板正确显示精美的Bootstrap 3单选按钮?

时间:2019-03-29 05:46:47

标签: symfony twig

我正在运行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()form_label()form_widget()的各种组合。我以几种不同的方式设置了attrlabel_attr,  但我不知道如何生成上面的HTML。似乎总是有多余的<div>或HTML导致其显示不正确。

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

目前正在运行,但是必须有一种更好的方法...

1 个答案:

答案 0 :(得分:0)

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)

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