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?
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]) }}
{# ... #}