user4144415
user4144415

Reputation:

How to customize Symfony 3.4 collection prototype

I know I'm not the first who's asking this question. But I tried everything to get it working.

At first, I have a entity named Assignment and another entity unit. Assignment has a manyToMany relation to Unit called units.

This creates the form:

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('pickupTime', DateTimeType::class, [
            'required' => true,
            'label' => 'Zeitpunkt Abholung',
            'date_widget' => 'single_text',
            'time_widget' => 'single_text',
        ])
        ->add('deliverTime', DateTimeType::class, [
            'required' => true,
            'label' => 'Zeitpunkt Lieferung (geplant)',
            'date_widget' => 'single_text',
            'time_widget' => 'single_text',
        ])
        ->add('customer', EntityType::class, [
            'required' => true,
            'label' => 'Kunde',
            'class' => Customer::class,
            'query_builder' => function (EntityRepository $er) use ($options) {
                return $er->createQueryBuilder('cu')
                    ->leftJoin('cu.client', 'c')
                    ->where('c.id = :cid')
                    ->setParameter('cid', $options['client_id'])
                    ->orderBy('cu.companyName', 'DESC');
            },
        ])
        ->add('pickupAddress', AddressType::class, [])
        ->add('deliverAddress', AddressType::class, [])
        ->add('units', CollectionType::class, [
            'entry_type' => UnitType::class,
            'allow_add' => true,
            'prototype' => true,
            'attr' => array(
                'class' => 'assignment-units',
            ),
        ]);
}

And here's the template for the form part of units:

        <div class="row">
            <div class="col">
                {{ form_label(form.units) }}
                <table class="table table-bordered table-light collection-form-wrapper">
                    <thead>
                    <tr>
                        <th>Bez.</th>
                        <th>Stück</th>
                        <th>Gewicht</th>
                        <th>Breite</th>
                        <th>Höhe</th>
                        <th>Tiefe</th>
                        <th></th>
                    </tr>
                    </thead>
                    <tbody>
                    {% for unit in form.units %}
                        <tr>
                            <td>{{ form_row(unit.name) }}</td>
                            <td>{{ form_row(unit.pieces) }}</td>
                            <td>{{ form_row(unit.weight) }}</td>
                            <td>{{ form_row(unit.width) }}</td>
                            <td>{{ form_row(unit.height) }}</td>
                            <td>{{ form_row(unit.depth) }}</td>
                            <td>
                                <a href="#" class="btn btn-danger btn-sm btn-delete" data-id="{{ loop.index }}"><i
                                            class="fa fa-trash"></i></a>
                            </td>
                        </tr>
                    {% else %}
                        <tr>
                            <td colspan="7" class="text-center">
                                <div class="p2">
                                    <i>
                                        <small>Noch keine Einträge vorhanden</small>
                                    </i>
                                </div>
                            </td>
                        </tr>
                    {% endfor %}
                    </tbody>
                    <tfoot>
                    <tr>
                        <td colspan="7">
                            <a href="#" class="btn btn-primary btn-sm" id="add-item"><i class="fa fa-plus"></i>
                                Hinzufügen</a>
                            <a href="#" class="btn btn-danger btn-sm" id="delete-all"><i class="fa fa-trash"></i> Tabelle leeren</a>
                        </td>
                    </tr>
                    </tfoot>
                </table>
            </div>
        </div>

{% form_theme form _self %}

{% block _units_entry_widget %}
    <tr>
        <td>{{ form_row(form.name) }}</td>
        <td>{{ form_row(form.pieces) }}</td>
        <td>{{ form_row(form.weight) }}</td>
        <td>{{ form_row(form.width) }}</td>
        <td>{{ form_row(form.height) }}</td>
        <td>{{ form_row(form.depth) }}</td>
        <td>
            <a href="#" class="btn btn-danger btn-sm btn-delete"><i
                        class="fa fa-trash"></i></a>
        </td>
    </tr>
{% endblock %}

But it doesn't work - it correspondents to the symfony docs (http://symfony.com/doc/master/form/form_customization.html#how-to-customize-a-collection-prototype) - but I get the error message Neither the property "name" nor one of the methods "name()", "getname()"/"isname()"/"hasname()" or "__call()" exist and have public access in class "Symfony\Component\Form\FormView"..

What's wrong with me? I don't understand where's the problem. When I try to override the widget of units with form_theme, the debugger show no fields of the collection units. When I delete the part with the form_theme, the fields are shown.

EDIT: Code of UnitType:

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('name')
        ->add('quantity')
        ->add('weight')
        ->add('width')
        ->add('height')
        ->add('depth');
}

Upvotes: 0

Views: 1314

Answers (1)

Roubi
Roubi

Reputation: 2106

I think the problem comes from the name of the block you use to customize the collection's items view.

The first part must be the parent form name.

The second part the collection field name.

The third part must always be _entry_row.

So (depending on the name of your forms) you should write something like:

{% block _assignment_units_entry_row %} instead of {% block _units_entry_widget %}

Upvotes: 1

Related Questions