代码之家  ›  专栏  ›  技术社区  ›  Rufinus

Symfony:如何避免自定义表单类型自动包装在div中?

  •  10
  • Rufinus  · 技术社区  · 10 年前

    用户类型窗体:

    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';
        }
    }
    

    导师类型表单:

    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';
        }
    }
    

    渲染时 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"> 当子节点不是子窗体时,如果是这种情况,请跳过它。

    TIA公司

    6 回复  |  直到 10 年前
        1
  •  5
  •   Zephyr    10 年前

    默认情况下,在基本表单主题中:

    {% 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应该来自模板的一个或另一个位。

    然而,在您的特定示例中,如果 表单用户行 如果定义了,则不使用第一位,并且如果 表单用户小部件 如果定义了,则不使用最后一位。

    回到你的问题。您的问题是: “我如何更改主题,以便所有自定义类型都不使用默认的form_row模板包装?”

    我认为这是一个问题:您希望您的TOP表单(包含所有子表单的表单)都有一种通用的呈现方式,在部分中。每个部分都将包含在一个具有class=“form group”的DIV中。您可能想加入一些额外的渲染操作,但我将仅限于此,以保持简单。

    然后,您需要做的是创建一个特殊的表单类型,并使所有TOP表单继承自该新表单类型。例如:

    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继承。

    模板主题化(我甚至可以这样说吗?),如果没有为 我的表单(_F) ,Symfony将理解此处使用的默认表单主题是 顶部表单 ,您可以这样定义:

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

    我应该补充一点,这是我已经遇到并解决的问题。告诉我这对你有什么好处。

    编辑:

    综上所述,您需要做的是:

    • 创建TopType表单类型,
    • 添加 顶部_窗体_小部件 块在表单主题中,
    • 对于所有根表单(即顶级表单、没有父级的表单),添加 获取父项() 方法,该方法将返回TopType表单的名称(“top_form”)
        2
  •  3
  •   egeloen    10 年前

    理论上,如果您覆盖 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"
    
        3
  •  3
  •   Elnur Abdurrakhimov Jon Skeet    10 年前

    我通常通过手动呈现嵌套表单的字段来解决这个问题:

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

    也许这不是最优雅的解决方案,但它对我很有效,我还没有找到一个优雅的解决方法。

        4
  •  1
  •   tlorens    5 年前

    Bootstrap 3.3.4我最终做到了这一点。

    它们是其中的关键部分:

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

    完整模板。

    {% 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 %}
    
        5
  •  0
  •   Alice    9 年前

    也许这不是一个优雅的解决方案,但对我来说很有效,因为我也在努力寻找解决方案。

    例如:

    {% 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>
    
        6
  •  -1
  •   enterx    10 年前

    尝试使用form_themes。

    首先,在父模板中定义表单主题:

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

    顺便用正确的名称替换BundleName、ControllerName和somesubform。

    然后使用以下命令进行渲染:

    {{ form_row(form.somesubform) }}