【问题标题】:Bootstrap 3: formatted checkboxes with Symfony & TwigBootstrap 3:使用 Symfony 和 Twig 格式化复选框
【发布时间】:2014-01-14 05:37:53
【问题描述】:

如何使用 Symfony Form Factory 和 Twig 创建一组格式化的复选框,如 Bootstrap documentation 中所述?

使用类似的东西

<div class="row">
  <div class="col-lg-4">
    {{ form_label(form.sample) }}
  </div>
  <div class="col-lg-8">
    {{ form_widget(form.sample) }}
  </div>
</div>

不会产生所需的输出:

a) Bootstrap 3 结构中的每个复选框,例如:

<div class="radio">
  <label>
    <input type="radio" ... />Option one
  </label>
</div>

b) 如果需要,还可以在两列或更多列中输出复选框:

<div class="row">
  <div class="col-lg-6 col-md-6">
    <div class="radio"> ... </div>
  </div>
  <div class="col-lg-6 col-md-6">
    <div class="radio"> ... </div>
  </div>
</div>

【问题讨论】:

  • 为了声称使用某些东西“不会产生预期的输出”,定义什么是您的例外输出会很有用。
  • 你说得对,我只考虑“预期输出” - 我现在编辑并完成了问题。

标签: forms symfony twig twitter-bootstrap-3 silex


【解决方案1】:

这样做的正确方法是创建自己的表单主题。我不会在这里写全部内容,但对你来说重要的是那些:

{% block choice_widget_expanded %}
{% spaceless %}
    <div {{ block('widget_container_attributes') }} class="my-form-choices">
    {% for child in form %}
        {{ form_widget(child) }}
    {% endfor %}
    </div>
{% endspaceless %}
{% endblock choice_widget_expanded %}

{% block checkbox_widget %}
{% spaceless %}
    <div class="checkbox">
        <label for="{{ id }}"><input type="checkbox" {{ block('widget_attributes') }}{% if value is defined %} value="{{ value }}"{% endif %}{% if checked %} checked="checked"{% endif %} />{{ label|trans({}, translation_domain) }}</label>
    </div>
{% endspaceless %}
{% endblock checkbox_widget %}

我从choice_widget_expanded 中删除了标签渲染,因此我可以在标签标签内添加复选框,就像您在解决方案中所使用的一样。但是您基本上可以在表单主题中做任何您想做的事情。如果你愿意,你也可以覆盖radio_widget

如果您仔细查看复选框周围的 div,我将其命名为“my-form-choices”类。你可以给它你想要的课程。它可能是“col-lg-8”,就像你一样,但对我来说,拥有一个通用类名更有意义,然后在你自己的 less 文件中使用 mixins。您的 less 文件将如下所示:

@import '../../../../../../vendor/twitter/bootstrap/less/bootstrap.less';

.my-form-row {
    .make-row();
}

.my-form-choices {
    .make-lg-column(8);
}

.my-form-row-label {
    .make-lg-column(4);
}

但这取决于你。如果您不想这样做,则不必这样做。最后,您可以通过像这样为您的页面启动树枝来使用您的主题:

{% extends 'MyOwnBundle::layout.html.twig' %}
{% form_theme form 'MyOwnBundle:Component:formtype.html.twig' %}

然后您就这样简单地显示该行(我在测试中使用的字段是可用性,您的是示例):

{{ form_row(form.availability) }}

我已经尝试过了(使用 Symfony 2.4),它可以工作。输出是这样的:

<div class="my-form-row">
    <div class="my-form-row-label">
        <label class="required">Availability</label>
    </div>
    <div class="my-form-choices" id="myown_website_contactmessage_availability">
        <div class="checkbox">
            <label for="myown_website_contactmessage_availability_0">
                <input type="checkbox" value="morning" name="myown_website_contactmessage[availability][]" id="myown_website_contactmessage_availability_0">
                Morning
            </label>
        </div>
        <div class="checkbox">
            <label for="myown_website_contactmessage_availability_1">
                <input type="checkbox" value="afternoon" name="myown_website_contactmessage[availability][]" id="myown_website_contactmessage_availability_1">
                Afternoon
            </label>
        </div>
        <div class="checkbox">
            <label for="myown_website_contactmessage_availability_2">
                <input type="checkbox" value="evening" name="myown_website_contactmessage[availability][]" id="myown_website_contactmessage_availability_2">
                Evening
            </label>
        </div>
    </div>
</div>

另请注意,我没有像您在解决方案中那样的子行。事实上,您的解决方案超出了您最初提出的问题。

编辑:这是拥有多列的解决方案

要拥有多个列,这里有一个快速的解决方案。首先,表单主题可能是这样的:

{% block choice_widget_expanded %}
{% spaceless %}
    <div class="my-form-choices-container">
        <div {{ block('widget_container_attributes') }} class="my-form-choices">
        {% for child in form %}
            {{ form_widget(child) }}
        {% endfor %}
        </div>
    </div>
{% endspaceless %}
{% endblock choice_widget_expanded %}

{% block checkbox_widget %}
{% spaceless %}
    <div class="my-form-choice">
        <div class="checkbox">
            <label for="{{ id }}"><input type="checkbox" {{ block('widget_attributes') }}{% if value is defined %} value="{{ value }}"{% endif %}{% if checked %} checked="checked"{% endif %} />{{ label|trans({}, translation_domain) }}</label>
        </div>
    </div>
{% endspaceless %}
{% endblock checkbox_widget %}

然后您的 less 文件将如下所示:

@import '../../../../../../vendor/twitter/bootstrap/less/bootstrap.less';

.my-form-row {
    .make-row();
}

.my-form-row-label {
    .make-lg-column(4);
}

.my-form-choices-container {
    .make-lg-column(8);
}

.my-form-choices {
    .make-row();
}

.my-form-choice {
    .make-md-column(6);
}

在此解决方案中,您可以通过更改列的大小来更改列数。细胞应堆叠整齐。在这种情况下,最好少编译(这里就不解释了)。我已经尝试过这个解决方案,并且效果很好。在这种情况下使用 less 的好处是,您可以在多个页面上使用相同的表单主题,并且只需为每个页面使用不同的“less”文件即可更改列数。

【讨论】:

  • 谢谢!到目前为止,我从未使用过表单主题,所以这个解决方案不在我的脑海中。这似乎是将表单工厂输出普遍适应 Bootstrap 3 的更好方法 - 我将在下一次仔细研究它。
【解决方案2】:

您需要访问包含复选框信息的表单变量:

form.sample.vars.form.children

现在您可以遍历复选框并访问值:

{% for children in form.sample.vars.form.children %}
  <div class="checkbox>
    <label>
      <input type="checkbox" name="{{ children.vars.full_name }}" id="{{ children.vars.id }}" value="{{ children.vars.value }}"{% if children.vars.data %} checked="checked"{% endif %} />
      {% if children.vars.label is defined %}
        {{ children.vars.label|trans }}
      {% else %}
        {{ children.vars.value|capitalize|trans }}
      {% endif %}
    </label>
  </div>
{% endfor %}

我将此代码放在 Twig 模板中,并添加一些逻辑来创建具有可变列的行,所以它看起来像这样:

{% set cols = columns|default(1) %}
{% set i = 1 %}
{% for children in childrens %}
  {% if i == 1 %}<div class="row">{% endif %}
  <div class="col-lg-{{ 12/cols }} col-md-{{ 12/cols }}">
    <div class="checkbox {{ class|default('') }}">
      <label>
        <input type="checkbox" name="{{ children.vars.full_name }}" id="{{ children.vars.id }}" value="{{ children.vars.value }}"{% if children.vars.data %} checked="checked"{% endif %} />
        {% if children.vars.label is defined %}
          {{ children.vars.label|trans }}
        {% else %}
          {{ children.vars.value|capitalize|trans }}
        {% endif %}
      </label>
    </div>
  </div>
  {% set i = i+1 %}
  {% if i > cols %}
    </div>
    {% set i = 1 %}
  {% endif %}
{% endfor %}
{% if i != 1 %}</div>{% endif %}

现在您可以在需要的地方添加此复选框模板:

<div class="row">
  <div class="col-lg-4">
    {{ form_label(form.sample) }}
  </div>
  <div class="col-lg-8">
    {% include 'checkbox.twig' with {childrens:form.sample.vars.form.children, columns:2} only %}
  </div>
</div>

上面的示例将返回格式良好的 Bootstrap 3 输出,其中两列中的复选框如下所示:

<div class="row">
  <div class="col-lg-4">
    <label class="required">Veranstalter</label>
  </div>
  <div class="col-lg-8">
    <div class="row">
  <div class="col-lg-6 col-md-6">
    <div class="checkbox ">
      <label><input type="checkbox" name="form[sample][]" id="form_sample_0" value="DUMMY">Dummy</label>
    </div>
  </div>
  <div class="col-lg-6 col-md-6">
    <div class="checkbox ">
      <label><input type="checkbox" name="form[sample][]" id="form_sample_1" value="DUMMY_1">Dummy 1</label>
    </div>
  </div>
</div>
<div class="row">
  <div class="col-lg-6 col-md-6">
    <div class="checkbox ">
      <label><input type="checkbox" name="form[sample][]" id="form_sample_2" value="DUMMY_2">Dummy 2</label>
    </div>
  </div>
</div>  

它易于使用,也适用于单选按钮 - 只需将类“checkbox”替换为“radio”即可。

【讨论】:

  • 我不明白,你问的同时回答了你的问题?
  • 这个答案得到了赞成,这是一个很好的努力。但这不是最好的解决方案。做到这一点的正确方法是通过形式主题,不包括另一个树枝。此外,此解决方案允许用户指定每行上的复选框数量。虽然这很有趣,但这不是问题的一部分。
【解决方案3】:

今天遇到了这个问题,我想我会分享我的解决方案。我已经有一个表单输入覆盖文件,但不喜欢我在其他地方找到的文件。所以像这样写了一个form_label块覆盖。

{% block form_label -%}
{% if label is not sameas(false) -%}
    {% if not compound -%}
        {% set label_attr = label_attr|merge({'for': id}) %}
    {%- endif %}
    {% if required -%}
        {% set label_attr = label_attr|merge({'class': (label_attr.class|default('') ~ ' required')|trim}) %}
    {%- endif %}
    {% if label is empty -%}
        {% set label = name|humanize %}
    {%- endif -%}
    <label{% for attrname, attrvalue in label_attr %} {{ attrname }}="{{ attrvalue }}"{% endfor %}>{% if 'checkbox' in block_prefixes %}{{ form_widget(form) }}{% endif %}{{ label|trans({}, translation_domain) }}</label>
{%- endif %}
{%- endblock form_label %}

然后 form_row 块像这样:

{% block form_row %}
{% spaceless %}

{% if 'checkbox' not in block_prefixes %}
   <div class="form-group"> 
        {{ form_label(form) }}
        {{ form_errors(form) }}
        {% if 'datetime' not in block_prefixes %}
            {{ form_widget(form, { 'attr': {'class': 'form-control'} }) }}
        {% else %}
            {{ form_widget(form) }}
        {% endif %}
    </div>
{% else %}
    {% import _self as forms %}
    <div class="checkbox">
        {{ form_label(form) }}
    </div>
{% endif %}

{% endspaceless %}
{% endblock %}

我选择这种方法是因为它允许我继续在模板中使用基本的 form(form) 方法。希望对您有所帮助。

【讨论】:

    【解决方案4】:

    如果您正在寻找此答案的简单版本(即您已经将 bootstrap_3_layout 主题应用到您的表单并且只想应用自定义标签文本)

    {{ form_widget( form.field, { 'label': 'Custom Label Text' } ) }}
    

    【讨论】:

      猜你喜欢
      • 2015-03-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-22
      • 1970-01-01
      • 1970-01-01
      • 2015-12-10
      • 1970-01-01
      相关资源
      最近更新 更多