Symfony:尝试自定义集合表单原型

zii*_*web 17 symfony

我有这样的形式:

class BillType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
       $builder
        ->add('user')
        ->add('numberPlate')
        ->add('servicesPerformed', CollectionType::class, array(
             'label' => false,
             'entry_type' => ServicePerformedType::class,
             'allow_add' => true,
        ))
        ->add('Save', SubmitType::class)
    ;
    /**
     * @param OptionsResolver $resolver
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'DefaultBundle\Entity\Bill'
        ));
    }
Run Code Online (Sandbox Code Playgroud)

作为ServicePerformedType类这样的:

class ServicePerformedType extends AbstractType
{
  public function buildForm(FormBuilderInterface $builder, array $options)
  {
     $builder
         ->add('description', TextareaType::class, array('label' => false))
         ->add('price', TextType::class, array('label' => false))
         ->add('quantity', TextType::class, array('label' => false));
  }

}
Run Code Online (Sandbox Code Playgroud)

这个模板用于呈现表单:

{{ form(form) }}
<a href="#">Add service</a>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<script type="text/javascript">

    var index = 0;
    $('a').on('click', function() {

        var prototype = $('#bill_servicesPerformed').data('prototype');

        prototype = prototype.replace(/_name_/g, index.toString());

        $('#bill_servicesPerformed').html(prototype);

        index++;
    })
</script>
Run Code Online (Sandbox Code Playgroud)

正如在文档中所说,要获得自定义原型,我应该在模板顶部添加以下行:

{% form_theme form _self %}

{% block _servicesPerformed_entry_widget %}
I WILL WRITE MY CUSTOM PROTOTYPE HERE
{% endblock %}
Run Code Online (Sandbox Code Playgroud)

但是,当我按下Add service我没有得到文本I WILL WRITE MY CUSTOME PROTOTYPE HERE,但是description,fields和以前quantity的ServicePerformedType班级相关..

注意:也许有其他方法可以自定义表单原型,但我对此感兴趣,所以非常感谢能够提供与这种方式相关的解决方案的人来定制表单原型,谢谢.

tft*_*ftd 19

我必须警告你,定制原型可能有点棘手.如果您更改FormType字段,则需要浏览模板并进行相同的更改,否则您的表单将无法呈现.

我喜欢做的是为该特定字段创建自定义模板,然后适当地自定义它.所以,看看你的代码我会做这样的事情:

  1. 创建一个页面模板 - 您将用于呈现整个页面的模板,包括表单.

    {# MyBundle/Resources/views/myPage.html.twig #}
    {% extends "::base.html.twig" %}
    
    
    {# This will tell the form_theme to apply the 
       `MyBundle:form/fields/servicePerformed.html.twig` template to your "form" #}
    
    {% form_theme form with [
        'MyBundle:form/fields/servicePerformed.html.twig'
    ] %}
    
    {% block body %}
        <div>
            {{ form_start(form) }}
                {{ form_rest(form) }}
            {{ form_end(form) }}
        </div>
    {% endblock %}
    
    Run Code Online (Sandbox Code Playgroud)
  2. 现在您需要创建模板MyBundle/Resources/views/form/fields/servicePerformed.html.twig.它将用于仅自定义servicePerformed字段.模板看起来应该是这样的

    {% macro service_template(fields) %}
        <tr>
            <td>I WILL WRITE MY CUSTOM PROTOTYPE HERE</td>
        </tr>
    {% endmacro %}
    
    {# 
       The block name must match your field name!
       You can find it by going into the debug toolbar -> Forms -> 
       click on your form field and then search for "unique_block_prefix". 
       Copy that and add "_widget" at the end.
    #}
    
    {% block _service_performed_widget %}
        <table data-prototype="{{ _self.service_template(form.vars.prototype)|e }}">
            {% for fields in form.children %}
                {{ _self.service_template(fields) }}
            {% endfor %}
        </table>
    {% endblock %}
    
    Run Code Online (Sandbox Code Playgroud)

我想要注意,在字段模板中,我正在传递原始原型_self.service_template(form.vars.prototype).通过这样做,您可以使用原始字段并在自定义原型中呈现它们.例如这段代码:

{% macro service_template(fields) %}
    <tr>
        <td>{{ form_widget(fields.description) }}</td>
    </tr>
{% endmacro %}
Run Code Online (Sandbox Code Playgroud)

将导致类似以下呈现的原型:

<tr>
    <td>
        <input type="text" id="service_performed___name___description" name="service[__name__][description]"/>
    </td>
</tr>
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用您的JavaScript操作它.

我希望这可以帮助你.

  • 这是互联网上唯一帮助这个荒谬的原型的东西.已经浪费了1个小时......非常感谢! (2认同)

Zep*_*hyr 5

实际上,以下划线开头的表单主题块_与具有特定名称的字段相关。

我的意思是,如果您的主表单BillType名为my_form,您将需要执行以下操作:

{% form_theme form _self %}

{% block _my_form_servicesPerformed_entry_widget %}
I WILL WRITE MY CUSTOM PROTOTYPE HERE
{% endblock %}
Run Code Online (Sandbox Code Playgroud)

这种方法的问题在于它涉及 的特定迭代BillType。如果您在其他地方使用此表单类型并为其提供不同的名称my_form_2,则必须添加一个相同的名为_my_form_2_servicesPerformed_entry_widget.