Symfony2 multiple Entities of same class in one Fo

2019-02-19 10:53发布

I want to render a form which has multiple Entities of same Class. I will display 2 fields, Price(type=text) and Enabled(type=checkbox).

I don't know how many I will have of those entities, so form will have to get them dynamically.

I have tried to do the following

public function buildForm(FormBuilderInterface $builder, array $options)
{

        $builder
            ->add('price', 'text', array(
                'label' => 'Price',
                'required' => true
            ))
            ->add('enabled','checkbox',array(
                'label'     => 'Use this currency',

            ))
        ;    
}

public function setDefaultOptions(OptionsResolverInterface $resolver)
{
    $resolver->setDefaults(array(
        'data_class'        => 'Osiris\Entity\Pricing',
        'csrf_protection'   => false
    ));
}

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

And in my Controller I have created my form like this:

$pricingForm = $this->createFormBuilder($prices)
               ->add('items','collection',array(
                   'required' => false,
                   'prototype' => true,
                   'type'    => new PricingType(),
               ))
                ->getForm()
            ;

In my twig I do:

{% for price in form_pricing %}
    <h2>Price</h2>
    <div class="row">{{ form_widget(price) }}</div>
{% endfor %}

However it comes only with h2 Prices and empty div with class=row. I feel like I am half way there, but I've no idea how to move on. If someone knows how to get fields on submit as well, I will really appreciate it.

2条回答
倾城 Initia
2楼-- · 2019-02-19 11:13

I found the solution,

the way I was creating the form in Controller was wrong! I had to do the following:

$pricingForm = $this->createFormBuilder(array('prices'=>$prices))
                ->add('prices','collection',array(
                    'required'       => true,
                    'allow_add'      => true,
                    'type'           => new PricingType(),
               ))
                ->getForm()
            ;

"allow_add => true" is necessary when working with collection, otherwise it will NOT add any of PricingType collection of entities to the form.

Then, because the form is built inside the controller "$this->createFormBuilder(array('prices'=>$prices))" , $prices array must be passed as an array with array keyname same as the one used in "->add('prices','collection',array(...)" , which is 'prices' so Symfony will know what to bind where. $prices is an array of Pricing objects array(0 => new Pricing()).

In my PricingType I have:

class PricingType extends AbstractType {

    public function buildForm(FormBuilderInterface $builder, array $options)
    {

        $builder
            ->add('price', 'text', array(
                'label' => false,
                'required' => true
            ))
            ->add('enabled','checkbox',array(
                'label'     => 'Use this currency',

            ))
        ;

    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class'        =>  'XXX\XXX\Entity\Pricing',
            'csrf_protection'   => false
        ));
    }

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

Here I need to have control over label attribute. I could not find the way for it( if anyone knows please post how to). I override my twig template as follows:

On the top we need next line of code:

    {% form_theme form_pricing _self %}

Then override row and widget as follows (it was a nightmare to debug):

{% block _form_prices_entry_row %}
    {% spaceless %}
        {{ form_widget(form) }}
    {% endspaceless %}
{% endblock %}

{% block _form_prices_entry_widget %}
    {% spaceless %}

        {{ form_row(form.price, { 'label' : form.vars.value.getCurrency().getTitle() } ) }}
        {{ form_row(form.enabled) }}

    {% endspaceless %}
{% endblock %}

In the body then, render form elements as follows:

{% for price in form_pricing.prices %}
                    <div class="price-row">{{ form_row(price) }}</div>
                {% endfor %}

I really hope this will help you guyz. It was a real nightmare to debug especially the twig file, I did it thanks to my clever colleague.

查看更多
叼着烟拽天下
3楼-- · 2019-02-19 11:23

I think you have missed a for loop in your twig file Check this example:

    {# store the prototype on the data-prototype attribute #}
    <ul id="email-fields-list" data-prototype="{{ form_widget(form.emails.vars.prototype)|e }}">
    {% for emailField in form.emails %}
        <li>
            {{ form_errors(emailField) }}
            {{ form_widget(emailField) }}
        </li>
    {% endfor %}
    </ul>

See the loop, I think that you need to add in your twig file.

In addition to loops you need to add JavaScript also.

Check this link:

http://symfony.com/doc/current/reference/forms/types/collection.html#adding-and-removing-items

Check the complete code. It will help you out to generate multiple entity forms from a single entity class using collection field type.

查看更多
登录 后发表回答