Symfony3 - 如何渲染嵌入式表单集合

Symfony3 - How to render Embedded collection of Forms

我还没有找到手动呈现包含集合的表单的解决方案。 这是我在树枝中的代码:

<ul id="document-fields-list" data-prototype="{{ form_widget(formulario.documentos.vars.prototype)|e }}">
    <div><button class="pull-right" href="#" id="add-another-document">Agregar documento</button></div>
    {% for documento in formulario.documentos %}
        <li>
            {{ form_label(documento) }}
            {{ form_widget(documento) }}
            <a href="#" class="remove-item">Eliminar</a>
        </li>
    {% endfor %}
</ul>

表格类型

在您的情况下,我们需要为 PersonaDocumento 创建 formType。想象一下,这个实体有字段 documentName:

class PersonaDocumentoType extends AbstractType
{
    /**
     * @param FormBuilderInterface  $builder
     * @param array                 $options
     * @SuppressWarnings(unused)
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('documentName', TextType::class, [
                'label'                 => false,
                'translation_domain'    => 'messages'
            ])
        ;
    }

    /**
     * @return string
     */
    public function getName()
    {
        return 'app_persona_documento_type';
    }

    /**
     * @return null|string
     */
    public function getBlockPrefix()
    {
        return 'app_persona_documento';
    }

    /**
     * @param OptionsResolver $resolver
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class'            => PersonaDocumento::class,
            'csrf_protection'       => true,
            'validation'            => true,
        ));
    }
}

包含collection

的表格

考虑你的实体 Formulario。它与 PersonaDocumento 具有 OneToMany 关系。表格将是:

class FormularioFormType extends AbstractType
{
    /**
     * @param FormBuilderInterface  $builder
     * @param array                 $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        // ...

        $builder
            ->add('documentos', CollectionType::class, [
                'entry_type'    => PersonaDocumentoType::class,
                'entry_options' => [
                    'label'         => false,
                ],
                'label'         => false,
                'allow_add'     => true,
                'allow_delete'  => true,
                'by_reference'  => false,  // Very important thing!
            ])
        ;
    }

    // ...
}

collection

的小部件

我们有一个表单 (FormularioFormType),其中包含 collection 个类型为 PersonaDocumentoType 的小表单。

您可以使用标准小部件在文件中创建新小部件,file is fields.html.twig 的名称:path_to_your_project/src/AppBundle/Resources/views/Form/fields.html.twig

块的名称将是 app_persona_documento_widget

因此,fields.html.twig 的示例:

{% trans_default_domain 'messages' %}

{% block app_persona_documento_widget %}
    {% spaceless %}
        <div class="form-group" {{ block('widget_container_attributes') }}>
            <div class="col-sm-12">
                {{ form_widget(form.name, {'attr' : { 'placeholder' : 'app.form.label.name'|trans , 'class' : 'form-control' }}) }}
            </div>
        </div>
    {% endspaceless %}
{% endblock app_persona_documento_widget %}

还要注意 "app_persona_documento_widget" - 从你的 getBlockPrefix() PersonaDocumentoType 加上字符串 "_widget"

组装而成

在config.yml

中注册新的表单主题
# Twig Configuration
twig:
    debug: '%kernel.debug%'
    strict_variables: '%kernel.debug%'
    form_themes:
        # other form themes
        # ...
        - 'AppBundle:Form:fields.html.twig'

以 parent 形式呈现 collection

            {{ form_start(formulario_form) }}
                <div class="form-group">
                    <label for="" class="col-sm-2 control-label">
                        Label
                    </label>
                    <div class="col-sm-10 documentos" data-prototype="{{ form_widget(formulario_form.documentos.vars.prototype)|e('html_attr') }}">
                        {% for document in formulario_form.documentos %}
                            <div>
                                {{ form_widget(document) }}
                            </div>
                        {% endfor %}
                    </div>
                </div>
                <span>
                    {{ form_errors(formulario_form) }}
                </span>
                {#  Here you can add another fields of form   #}
            {{ form_end(formulario_form) }}

当然,你还需要按钮:一个"Add another document"按钮和每个"Remove"按钮"Documento"项。

Symfony 文档建议我们为此目的使用 JavaScript。 您可以阅读更多 here in official docs

您还可以安装 Ninsuo/symfony-collection - 一个 jQuery 插件,用于管理从 Symfony 添加、删除和移动元素 collection