Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Build a form having a checkbox for each entity in a doctrine collection

I'm displaying an html table for a filtered collection of entities and I want to display a checkbox in each row as part of a form which will add the selected entities to a session var.

I'm thinking that each checkbox should have the entity id as its value and I'll get an array of ids from the form field data (ok, so the value ought to be an indirect ref to the entity, but for the sake of simplicity).

I've tried creating a form Type with a single entity type field, mapped to the id property of the entity and embedded into another form Type which has a collection type field.

class FooEntitySelectByIdentityType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('foo_id', 'entity', array(
            'required'  => false,
            'class'    => 'MeMyBundle:FooEntity',
            'property' => 'id',
            'multiple' => true,
            'expanded' => true
        ));
    }

# ...

and

class FooEntitySelectionType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('identity', 'collection', array(
            'type'   => new FooEntitySelectByIdentityType,
            'options'  => array(
                'required' => false,
                'multiple' => true,
                'expanded' => true,
                'attr'     => array('class' => 'foo')
            ),
        ));
    }

# ...

and in a controller the form is created with a collection of entities as the initial data

$form = $this
    ->createForm(
        new \Me\MyBundle\Form\Type\FooEntitySelectionType,
        $collection_of_foo
    )
    ->createView()
;

When the form is rendered there is a single label for the identity field, but no widgets.

Is it even possible to use entity and collection type fields in this particular way? If so, what might I be doing wrong?

like image 867
jah Avatar asked Feb 01 '13 02:02

jah


2 Answers

I think this will answer your question.

Forget the FooEntitySelectionType. Add a property_path field option to FooEntitySelectByIdentityType and set the data_class option to null:

class FooEntitySelectByIdentityType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('foo_id', 'entity', array(
            'required'      => false,
            'class'         => 'MeMyBundle:FooEntity',
            'property'      => 'id',
            'property_path' => '[id]', # in square brackets!
            'multiple'      => true,
            'expanded'      => true
        ));
    }

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

# ...

and in your controller, build the FooEntitySelectByIdentityType:

$form = $this
    ->createForm(
        new \Me\MyBundle\Form\Type\FooEntitySelectByIdentityType,
        $collection_of_foo
    )
    ->createView()
;

and then in the controller action which receives the POSTed data:

$form = $this
    ->createForm(new \Me\MyBundle\Form\Type\FooEntitySelectByIdentityType)
;
$form->bind($request);
if ($form->isValid()) {
    $data = $form->getData();
    $ids  = array();
    foreach ($data['foo_id'] as $entity) {
        $ids[] = $entity->getId();
    }
    $request->getSession()->set('admin/foo_list/batch', $ids);
}

and finally, in your twig template:

{# ... #}
{% for entity in foo_entity_collection %}
    {# ... #}

    {{ form_widget(form.foo_id[entity.id]) }}

    {# ... #}
like image 186
jah Avatar answered Sep 20 '22 17:09

jah


If someone is looking for solution for Symfony >=2.3

You have to change this:

    $data = $form->getData();
    $ids  = array();
    foreach ($data['foo_id'] as $entity) {
        $ids[] = $entity->getId();
    }

to this:

    $data = $form['foo_id']->getData();
    $ids = array();
    foreach ($data as $entity) {
        $ids[] = $entity->getId();
    }
like image 37
user1483208 Avatar answered Sep 20 '22 17:09

user1483208