简体   繁体   中英

Symfony3 form_widget render 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?

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.

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 [TwigBridge] Make sure we always render errors. Eventhough labels are disabled .

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM