在Symfony 2表单中自定义data-prototype属性

时间:2016-06-06 09:24:20

标签: forms symfony twig

我正在尝试按照Symfony 2.7文档使用Embed a Collection of Forms创建custom Collection Prototype

问题是,我无法按照文档中的说明创建自定义集合原型。

如示例中所示,有两个简单的类: 一个Task类,用于管理任务的描述以及任意数量的标记,由其自己的Tag

表示
class Task {
    protected $description;
    protected $tags;

    public function __construct() {
        $this->tags = new array();
    }

    // Getter & Setter for description + additional addTag & removeTag methods
    // ...

    // Tags getter
    public function getTags() {
        return $this->tags;
    }
}

class Tag {
    protected $name;
    // ... setName(...), getName()...
}

这些是自定义表单类型:

class TaskType extends AbstractType {
    public function buildForm(FormBuilderInterface $builder, array $options) {
        $builder->add('description');
        $builder->add('tags', 'collection', array('type' => new TagType()));
    }

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

    // ...
}


class TagType extends AbstractType {
    public function buildForm(FormBuilderInterface $builder, array $options) {
        $builder->add('name');
    }

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

    // ...
}

呈现表单的Twig文件

{{ form_start(form) }}
    {# render the task's only field: description #}
    {{ form_row(form.description) }}

    {# render tags - use table instead of ul as in example #}
    <div class="table-responsive">
        <table class="table">
            <thead>
                <th>{{ 'task.tag.headline'|trans }}</th>    
            </thead>
            <tbody class="tags-container" data-prototype="{{ form_widget(form.tags.vars.prototype)|e('html_attr') }}">   
                {{ form_row(form.rules) }}          
            </tbody>
        </table>
    </div>
{{ form_end(form) }}

这很好,并在表格中呈现tags列表。 但是,此代码使用默认原型,(当然)不会为不同的标记创建表行。

我尝试添加代码以使用自定义原型作为described in the docs。然而,文档没有说明添加此代码的位置或如何使用它:

使用自定义原型代码的Twig代码

{{ form_start(form) }}
    {# Custom Prototype Code from docs #}
    {% form_theme form _self %}

    {% block _tags_entry_widget %}
        <tr>
            <td>{{ form_widget(form.name) }}</td>
        </tr>
    {% endblock %} 


    {# render the task's only field: description #}
    {{ form_row(form.description) }}

    {# render tags - use table instead of ul as in example #}
    <div class="table-responsive">
        <table class="table">
            <thead>
                <th>{{ 'task.tag.headline'|trans }}</th>    
            </thead>
            <tbody class="tags-container" data-prototype="{{ form_widget(form.tags.vars.prototype)|e('html_attr') }}">   
                {{ form_row(form.rules) }}          
            </tbody>
        </table>
    </div>
{{ form_end(form) }}

使用这样的自定义原型代码会导致错误:

  

方法&#34;名称&#34; for object&#34; Symfony \ Component \ Form \ FormView&#34;不   不存在于&#34; MyAppBundle:任务:task.html.twig&#34;

这听起来很合理,因为name属于Tag类,而不属于Task类。

问题1:如何在模板中使用/访问Tag表单?**

我从原型模板中删除了<td>{{ form_widget(form.name) }}</td>,并将其替换为<td>Test</td>以查看是否使用了该模板。结果:模板未使用且无效。

问题2:设置/激活原型模板的正确方法是什么?

我发现其他线程处理原型问题/问题。答案提出了使用宏,外部twig文件等的不同解决方案。由于Symfony文档似乎在不使用宏等黑客的情况下在同一文件中提供解决方案,我想知道实现此解决方案。 < / p>

1 个答案:

答案 0 :(得分:3)

这对我有用 - 对不起 - 这是Symfony 3,但你应该能够翻译。

在PersonType类的buildForm方法中,我的CollectionType为电子邮件

             ->add( 'emails', CollectionType::class, [
                'label' => 'common.email',
                'entry_type' => AppEmailType::class,
                'by_reference' => true,
                'required' => false,
                'label' => false,
                'empty_data' => null,
                'allow_add' => true,
                'allow_delete' => true,
                'delete_empty' => true,
                'mapped' => false,
                'prototype_name' => '__email__'
                ] )

呈现PersonType的模板包括类似的电子邮件

{% include 'common/emails.html.twig' with {'form': form.emails } %}

<强>公共/ emails.html.twig

此模板是集合的容器

   <div class="emails">
        <span class="sub-form-legend">{{'common.email'|trans}}</span>
        {{form_row(form)}}
        {% if form.vars.allow_add %}
        <div class="add-one-more-row">{{ 'common.add_one_more'|trans}}</div>
        {% endif %}
    </div>

fields.html.twig 中,我有一个特定于表单的entry_row模板,该模板使用在同一文件中定义的通用电子邮件模板。

{% block _user_person_emails_entry_row %}
    {{ block('_emails_entry_row') }}
{% endblock %}

{% block _emails_entry_row %}
    {% spaceless %}
        <div class="form-row email">
            <span class="type-select">{{ form_widget(form.type) }}</span>
            <span class="input">{{ form_widget(form.email) }}</span>
            <span class="comment">{{ form_widget(form.comment) }}</span>
            <span class="remove-form-row" title="{{'common.remove'|trans}}" id="email-__email__"><i class="fa fa-remove"></i></span>
        </div>
    {% endspaceless %}
{% endblock %}

要查找名称,请跟踪表单的名称,并在下面添加下划线。使用 {{dump(form)}} 获取唯一名称。

HTML将放在 data-prototype 属性中。