3

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');
                }
            ))

...

Geoff Maddock
  • 1,700
  • 3
  • 26
  • 47

2 Answers2

2

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.

guhemama
  • 107
  • 3
  • 7
0

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

habibun
  • 1,552
  • 2
  • 14
  • 29
  • I see what you're doing here, and doing a version of this is working for me. But I still feel like I'm missing something that will let this work more simply. – Geoff Maddock Dec 06 '17 at 17:45