Symfony:как избежать автоматической упаковки пользовательских типов форм в div?

Форма UserType:

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' => 'VendorModelEntityUser',
        ));
    }

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

Форма TutorType:

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' => 'VendorModelEntityTutor',
            'cascade_validation' => true,
        ));
    }

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

при рендеринге UserType отображается внутри div, я не могу найти способ преодолеть это.

форма отображается как

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>

на form_tutor_user завернут в собственную форму-группу div. Я попытался перезаписать form_tutor_user_widget, но это один уровень для глубокого. (И только быстрое исправление, оно должно быть глобально применено ко всем типам форм - Классы)

как я могу изменить тему, чтобы все пользовательские типы не были обернуты шаблоном form_row по умолчанию?

или как я узнаю в веточке, когда отображается "подформа"? поэтому я могу решить распечатать <div class="form-group"> когда дочерний узел не является подформой, или пропустите его, если это так.

ТИА

5 ответов


по умолчанию, в теме основной форме:

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

и, для пользовательских составных форм:

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

если вы не изменили что-то здесь, DIV, который вы видите, должен исходить из одного или другого бита шаблона.

однако в вашем примере specfic, если form_tutor_user_row определено, Первый БИТ никогда не используется, и если form_tutor_user_widget определено, последний бит не используется.

обратно в вопрос. Ваш вопрос : " как я могу изменить тему, чтобы все пользовательские типы не были обернуты шаблоном form_row по умолчанию?"

вот проблема, как я ее вижу: вы хотите, чтобы ваши верхние формы (форма, в которую включены все подформы) имели общий способ рендеринга в разделах. Каждый раздел будет включен в DIV с class= "form-group". Возможно, вы захотите добавить некоторые дополнительные операции рендеринга, но я ограничусь этим, чтобы сохранить вещи простыми.

что вам нужно сделать, так это создать тип формы specfic и сделать все ваши верхние формы наследуемыми от этого нового типа формы. Например:

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

... и наследственная форма:

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

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

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

как вы можете видеть, нет необходимости делать наследование PHP для наследования формы theming для работы.

Template-theming-wise (могу ли я даже сказать это?), если конкретная тематизация формы не установлена для my_form, Symfony поймет, что тема формы по умолчанию для использования здесь-тема формы top_form, что вы можете определить как таковой:

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

Я должен добавить, что это проблема, с которой я уже столкнулся и решил. Скажи мне, как это работает для вас.

Edit:

чтобы подвести итог, вам нужно сделать следующее:

  • создайте Тип формы TopType,
  • добавить top_form_widget блок в форме тема,
  • для всех ваших корневых форм (т. е. форм верхнего уровня, форм, у которых нет родителя) добавьте getParent() метод, который вернет имя вашей формы TopType ("top_form")

обычно я решаю эту проблему путем рендеринга полей вложенной формы вручную:

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

вероятно, это не самое элегантное решение, но оно работает для меня, и я еще не искал элегантного.


теоретически, если вы переопределите form_widget_compound блок в глобальной теме формы таким образом, он должен работать так, как вы хотите:

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

и зарегистрировать тему формы:

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

может быть, это не элегантное решение, но работает для меня, потому что я также пытался найти решение.

в качестве примера:

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

попробуйте использовать form_themes.

во-первых, в Родительском шаблоне вы определяете тему формы:

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

btw замените BundleName, ControllerName и somesubform собственными именами.

затем отобразите его с помощью:

{{ form_row(form.somesubform) }}