douge3830
2018-02-16 13:03
浏览 160
已采纳

Symfony form_widget呈现form_row

I try to render a form input in a view but instead of separating label, errors and widget, it renders the whole row of the input.

MyType.php

/**
 * {@inheritdoc}
 */
public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('email', EmailType::class, [
            'label' => 'Email',
            'required' => true,
        ])
        ->add('emailIsPublic', CheckboxType::class, [
            'label' => 'Make e-mail public (can be seen by everyone)',
            'required' => false,
            'attr' => [
                'class' => 'switch',
            ]
        ])
        ->add('submit', SubmitType::class, [
            'label' => 'Save changes',
            'attr' => [
                'class' => 'btn btn-outline-primary float-right',
            ]
        ]);
}

my-view.html.twig

{{ form_start(edit_form) }}
    <div>
        {{ form_label(edit_form.emailIsPublic) }}
    </div>
    <div>
        {{ form_errors(edit_form.emailIsPublic) }}
    </div>
    <div>
        {{ form_widget(edit_form.emailIsPublic) }}
    </div>
{{ form_end(edit_form, {'render_rest': false}) }}

Generated HTML

<form name="appbundle_my" method="post">
    <div></div>
    <div></div>
    <div>
        <div class="form-check">
            <label class="form-check-label">
                <input id="appbundle_my_emailIsPublic" name="appbundle_my[emailIsPublic]" class="switch form-check-input" value="1" type="checkbox"> Make e-mail public (can be seen by everyone)
            </label>
        </div>
    </div>
</form>

As we can see in the generated HTML, form_label and form_errors are empty and form_widget renders what form_row should render. Why?

  • 写回答
  • 好问题 提建议
  • 关注问题
  • 收藏
  • 邀请回答

2条回答 默认 最新

  • dongsaoshuo4326 2018-03-22 12:35
    已采纳

    As I saw here: https://github.com/symfony/symfony/issues/26540#issuecomment-375232354

    This behaviour seems to be a bug specific to the usage of the Bootstrap 4 Form theme.

    That's specific to the Bootstrap 4 theme and it seems to be related to the changes made in #26591 [TwigBridge] Make sure we always render errors. Eventhough labels are disabled.

    I will wait for an update of Symfony to solve this.

    已采纳该答案
    评论
    解决 无用
    打赏 举报
  • doulian4762 2018-02-16 13:47

    I'm not very used to twig and form themes but i'm pretty sure you can't split up the row into these 3 pats because of the checkbox type. When using a checkbox widget the label is kind of baked into the rendering of the widget. When rendering a form_row it renders the 3 parts label, error and widget while the checkbox widget itself also renders the label. Which makes kind of sense given that the label is pretty much a vital information about the use of the checkbox.

    {% block checkbox_widget -%}
        {%- set parent_label_class = parent_label_class|default(label_attr.class|default('')) -%}
        {%- set attr = attr|merge({class: (attr.class|default('') ~ ' form-check-input')|trim}) -%}
        {% if 'checkbox-inline' in parent_label_class %}
            {{- form_label(form, null, { widget: parent() }) -}}
        {% elseif 'form-check-inline' in parent_label_class %}
            <div class="form-check{{ not valid ? ' form-control is-invalid' }} form-check-inline">
                {{- form_label(form, null, { widget: parent() }) -}}
            </div>
        {% else -%}
            <div class="form-check{{ not valid ? ' form-control is-invalid' }}">
                {{- form_label(form, null, { widget: parent() }) -}}
            </div>
        {%- endif -%}
    {%- endblock checkbox_widget %}
    

    You can try to overwrite the block for this specific use-case by adding something like this into the template:

    {% form_theme form _self %}
    
    {% block _edit_form_emailIsPublic_row %}
      {% spaceless %}
        ####build your markup for the checkbox here, use default on hot to access the needed informations etc.####
      {% endspaceless %}
    {% endblock %}
    

    or just completely render it yourself without redefining the used block, by writing the markup yourself and just get some vital things like name, label values etc. from the form object (edit_form.emailIsPublic.vars.label for example) without calling any helper and set the field to rendered afterwards {% edit_form.emailIsPublic.setRendered %} if you want to remove the render_rest: false

    Hope this can get you in the right direction. Forms can be quite a pain.

    评论
    解决 无用
    打赏 举报

相关推荐 更多相似问题