Geoff Maddock
Geoff Maddock

Reputation: 1812

Symfony 3.3 Form - EntityType field does not select option

For some unknown reason, the EntityType form field will not display the selected option on submit, even though the name of the column matches and data passes.

I've created a form that I'm using to select some values that will filter a list of products.

<?php namespace AppBundle\Filter;

use AppBundle\Entity\ProductCategory; 
use AppBundle\Repository\ProductCategoryRepository; 
use Symfony\Bridge\Doctrine\Form\Type\EntityType; 
use Symfony\Component\Form\AbstractType; 
use Symfony\Component\Form\FormBuilderInterface;

class ProductFilterType extends AbstractType {
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('id', null, [
                'required'   => false,
                'label'      => 'SKU'
            ])
            ->add('productCategory', EntityType::class,
                array(
                    'class' => ProductCategory::class,
                    'choice_label' => 'name',
                    'choice_value' => 'id',
                    'placeholder' => '',
                    'label_attr' => array('title' => 'Category for this product'),
                    'query_builder' => function (ProductCategoryRepository $v) {
                        return $v->createQueryBuilder('v')
                            ->orderBy('v.name',' ASC');
                    }
                ))
            ->add('name', null, [
                'required'   => false,
            ])
            ->add('description', null, [
                'required'   => false,
            ])


        ;
    }


    /**
     * {@inheritdoc}
     */
    public function getBlockPrefix()
    {
        return 'app_bundle_product_filter_type';
    } }

The form renders as expected, and it submits a post to the same URL, which filters based on the value received from the request.

That works ok.

However, when the form is re-rendered, the option that was selected before the form filter submission is no longer selected. All other inputs are repopulating.

enter image description here

I did notice that when I'm working with a form that is bound to an Entity (ie: Editting and saving the entity) and using the ConfigureOptions method to set the data class, that the EntityType form field works as expected. However, I need it to work in this case where the overall form is not bound to an Entity.

EDIT: Doing these steps worked for me...but it seems a bit odd.

Injected entity manager into the form constructor:

public $em;

public function __construct(EntityManager $em) {
    $this->em = $em;
}

Then updated the EntityType form field to get the object based on the array value:

->add('productCategory', EntityType::class,
            array(
                'class' => ProductCategory::class,
                'choice_label' => 'name',
                'choice_value' => 'id',
                'placeholder' => '',
                'label_attr' => array('title' => 'Category for this product'),
                'data' =>  $this->em->getReference("AppBundle:ProductCategory",
                    isset($options['data']['productCategory']) ? $options['data']['productCategory'] : 0),
                'query_builder' => function (ProductCategoryRepository $v) {
                    return $v->createQueryBuilder('v')
                        ->orderBy('v.name',' ASC');
                }
            ))

...

Upvotes: 3

Views: 3703

Answers (2)

guhemama
guhemama

Reputation: 107

Another solution is using a Data Transformer.

Remove the data attribute from the productCategory type, and add a data transformer to the end of the build method:

    $builder->get('productCategory')
        ->addModelTransformer(new CallbackTransformer(
            function ($id) {
                if (!$id) {
                    return;
                }

                return $this->em->getRepository('AppBundle:ProductCategory')->find($id);
            },
            function($category) {
                return $category->getId();
            }
        ));

If you use the same transformer in multiple places, you can extract it into its own class.

Upvotes: 2

habibun
habibun

Reputation: 1630

My workaround was like this ... pass data and entity manager to formType.

$form = $this->createForm(new xxxType($this->get('doctrine.orm.entity_manager')), xxxEntity, array(
        'method' => 'POST',
        'action' => $this->generateUrl('xxxurl', array('id' => $id)),
        'selectedId' => xxxId,
    ));

setDefaultOptions in form Type initialize as an empty array for selectedId

$resolver->setDefaults(array(
        'data_class' => 'xxx',
        'selectedId' => array()
    ));

and in builder

->add('productCategory', EntityType::class,
            array(
                'class' => ProductCategory::class,
                'choice_label' => 'name',
                'choice_value' => 'id',
                'placeholder' => '',
                'label_attr' => array('title' => 'Category for this product'),
                'query_builder' => function (ProductCategoryRepository $v) {
                    return $v->createQueryBuilder('v')
                        ->orderBy('v.name',' ASC');
                },
                'data'=>$this->em->getReference("xxx",$options['selectedId'])
            ))

for more details, you can see this answer Symfony2 Setting a default choice field selection

Upvotes: 0

Related Questions