Symfony:Wie vermeide ich, dass benutzerdefinierte Formulartypen automatisch in ein Div eingeschlossen werden?

StackOverflow https://stackoverflow.com//questions/22014792

Frage

Benutzertyp Formular:

class UserType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('email', 'email', ['label' => 'EMail']);
        // various other fields....
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'validation_groups' => array('registration'),
            'data_class' => 'Vendor\Model\Entity\User',
        ));
    }

    public function getName()
    {
        return 'form_user';
    }
}

Tutortyp Formular:

class TutorType extends Translate
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('user', new UserType(), ['label' => false]);

        $builder->add('school', 'entity', [
            'class' => 'Model:School',
            'property' => 'name',
            'label' => 'Label'
        ]);

        // Various other fields
        $builder->add('save', 'Submit');
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            //'validation_groups' => array('registration'),
            'data_class' => 'Vendor\Model\Entity\Tutor',
            'cascade_validation' => true,
        ));
    }

    public function getName()
    {
        return 'form_tutor';
    }
}

Beim Rendern wird die UserType wird in einem Div gerendert, kann ich keinen Weg finden, dies zu überwinden.

Das Formular wird wie folgt gerendert

the result

<form name="form_tutor"
      method="post"
      action=""
      novalidate="novalidate"
      class="form-horizontal form-horizontal"
      id="form_tutor">
    <div id="form_tutor"
         novalidate="novalidate"
         class="form-horizontal">
        <div class="form-group">
            <div class="col-lg-10">
                <div id="form_tutor_user">
                    <div class="form-group">
                        <label class="col-lg-2 control-label aaaa required"
                             for="form_tutor_user_email">EMail</label>

                        <div class="col-lg-10">
                            <input type="email"
                                 id="form_tutor_user_email"
                                 name="form_tutor[user][email]"
                                 required="required"
                                 class="form-control" />
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <div class="form-group">
            <label class="col-lg-2 control-label aaaa required"
                 for="form_tutor_tutorType">Type</label>

            <div class="col-lg-10">
                <select id="form_tutor_tutorType"
                     name="form_tutor[tutorType]"
                     class="form-control">
                    </select>
            </div>
        </div>

        <div class="form-group">
            <div class="col-lg-offset-2 col-lg-10">
                <button type="submit"
                     id="form_tutor_save"
                     name="form_tutor[save]"
                     class="btn btn-default">Speichern</button>
            </div>
        </div><input type="hidden"
             id="form_tutor__token"
             name="form_tutor[_token]"
             class="form-control"
             value="s6i6zPxJs7KU5CiEe8i6Ahg_ca8rc2t5CnSk5yAsUhk" />
    </div>
</form>

Der form_tutor_user ist in eine eigene Form verpackt-group div.Ich habe versucht, das form_tutor_user_widget zu überschreiben, aber dies ist eine Ebene zu tief.(Und nur eine schnelle Lösung, es sollte global auf alle Formulartypklassen angewendet werden)

Wie kann ich das Design ändern, damit nicht alle benutzerdefinierten Typen mit der Standardvorlage form_row umbrochen werden?

Oder woher weiß ich im Zweig, wann ein "Unterformular" gerendert wird?also kann ich mich entscheiden, das zu drucken <div class="form-group"> wenn der untergeordnete Knoten kein Unterformular ist, oder überspringen Sie es, wenn dies der Fall ist.

TIA

War es hilfreich?

Lösung

Standardmäßig im Basisformular-Design:

{% block form_row %}
{% spaceless %}
    <div>
        {{ form_label(form) }}
        {{ form_errors(form) }}
        {{ form_widget(form) }}
    </div>
{% endspaceless %}
{% endblock form_row %}

Und für kundenspezifische zusammengesetzte Formen:

{% block form_widget_compound %}
{% spaceless %}
    <div {{ block('widget_container_attributes') }}>
        {% if form.parent is empty %}
            {{ form_errors(form) }}
        {% endif %}
        {{ block('form_rows') }}
        {{ form_rest(form) }}
    </div>
{% endspaceless %}
{% endblock form_widget_compound %}

Sofern Sie hier nichts geändert haben, sollte das angezeigte DIV entweder aus dem einen oder anderen Teil der Vorlage stammen.

In Ihrem speziellen Beispiel jedoch, wenn formular_tutor_benutzer_zeile definiert ist, wird das erste Bit nie verwendet, und wenn formular_tutor_benutzer_widget definiert ist, wird das letzte Bit nie verwendet.

Zurück zu deiner Frage.Ihre Frage ist :"Wie kann ich das Design ändern, damit nicht alle benutzerdefinierten Typen mit der Standardvorlage form_row umbrochen werden?"

Hier ist das Problem so wie ich es sehe:sie möchten, dass Ihre TOP-Formulare (das Formular, in dem alle Unterformulare enthalten sind) alle eine gemeinsame Art des Renderns in Abschnitten haben.Jeder Abschnitt wird in ein DIV mit class = "form-group" aufgenommen.Vielleicht möchten Sie einige zusätzliche Rendervorgänge einbauen, aber ich werde mich darauf beschränken, um die Dinge einfach zu halten.

Was Sie dann tun müssen, ist, einen bestimmten Formulartyp zu erstellen und alle Ihre TOP-Formulare von diesem neuen Formulartyp erben zu lassen.Beispielsweise:

class TopType extends AbstractType
{
    public function getName()
    {
        return 'top_form';
    }
}

...und eine vererbte Form:

class MyFormType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        ...
    }

    public function getName()
    {
        return 'my_form';
    }

    public function getParent()
    {
        return 'top_form';
    }
}

Wie Sie sehen, ist es nicht erforderlich, eine PHP-Vererbung vorzunehmen, damit die Vererbung von Formularthemen funktioniert.

Template-Theming-weise (kann ich das überhaupt sagen?), wenn kein spezifisches Formular-Thema für festgelegt ist mein_formular, Symfony wird verstehen, dass das hier zu verwendende Standard-Formularthema das Formularthema von ist Topform, die Sie als solche definieren können:

{% block top_form_widget %}
{% spaceless %}
    {% for child in form %}
        <div class="form-group">
            {{ form_widget(child) }}
        </div>
    {% endfor %}
    {{ form_rest(form) }}
{% endspaceless %}
{% endblock top_form_widget %}

Ich sollte hinzufügen, dass dies ein Problem ist, auf das ich bereits gestoßen bin und das ich gelöst habe.Sag mir, wie das bei dir funktioniert.

Bearbeiten:

Um es zusammenzufassen, was Sie tun müssen, ist:

  • Erstellen Sie den Formulartyp TopType,
  • Fügen Sie die startseite _ Formular _ Widget blockieren Sie in Ihrem Formularthema,
  • Für alle Ihre Wurzelformen (z.formulare der obersten Ebene, Formulare, die kein übergeordnetes Element haben), fügen Sie ein getParent() methode, die den Namen Ihres TopType-Formulars zurückgibt ("top_form")

Andere Tipps

Theoretisch, wenn Sie die überschreiben form_widget_compound blockieren Sie auf diese Weise ein globales Formularthema, es sollte so funktionieren, wie Sie es möchten:

// app/Resources/views/form.html.twig

{% block form_widget_compound %}
    {% if form.parent is empty %}
        <div {{ block('widget_container_attributes') }}>
        {{ form_errors(form) }}
    {% endif %}
    {{ block('form_rows') }}
    {{ form_rest(form) }}
    {% if form.parent is empty %}
        </div>
    {% endif %}
{% endblock %}

Und registrieren Sie Ihr Formularthema:

// app/config/config.yml
twig:
    form:
        resources:
            - "::form.html.twig"

Normalerweise löse ich dieses Problem, indem ich die Felder des verschachtelten Formulars manuell rendere:

{{ form_row(form.tutor.school) }}
{{ form_row(form.tutor.user.email) }}

Wahrscheinlich ist das nicht die eleganteste Lösung, aber es funktioniert für mich und ich habe noch nicht nach einer eleganten gesucht.

Bootstrap 3.3.4 Am Ende habe ich das gemacht.

Sie sind ein wichtiger Teil davon:

 <div class="{% if form.parent.parent is empty %}form-group{% endif %}{% if (not compound or force_error|default(false)) and not valid %} has-error{% endif %}">

Vollständige Vorlage.

{% block form_row -%}
    <div class="{% if form.parent.parent is empty %}form-group{% endif %}{% if (not compound or force_error|default(false)) and not valid %} has-error{% endif %}">
        {% if form.parent.parent is null and label is not empty %}
            {{- form_label(form) -}}
        {% elseif label is empty %}
            {{- form_label(form) -}}
        {% endif %}
        {% if compound is empty %}<div class="{{ block('form_group_class') }}">{% endif %}
            {{- form_widget(form) -}}
            {{- form_errors(form) -}}
        {% if compound is empty %}</div>{% endif %}
    </div>
{%- endblock form_row %}

Vielleicht ist es keine elegante Lösung, funktioniert aber für mich, weil ich auch versucht habe, die Lösung zu finden.

Als Beispiel:

{% for custom_field in form.custom_fields %}
<div class="edit_custom">
{{ form_row(custom_field.name) }}
{{ form_row(custom_field.value) }}
</div>
{% endfor %}

<script>
$('.edit_custom').find('input').unwrap();
</script>

Versuchen Sie es mit form_themes .

Definieren Sie zunächst in Ihrer übergeordneten Vorlage das Formularthema:

{% form_theme form with ['BundleName:ControlerName:somesubform_form.html.twig'] %}

ersetzen Sie übrigens BundleName, controllerName und somesubform durch die richtigen Namen.

dann rendere es mit:

{{ form_row(form.somesubform) }}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top