Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Symfony 2.1: How to pass parameter to custom form field type

I'm building a custom form field type extending from 'EntityType'. I always want to return a subset of elements based on option passed.

In my Type:

$builder->add('Categories','choice_category', array('code'=> 'CAT1', 'multiple'=> true))   ;

I've declared choice_category as service. work ok!.

  bt.form.type.category:
  class: My\MBundle\Form\Type\CategoryType
  tags:
      - { name: form.type, alias: choice_category }

In CategoryChoiceType.php

public function setDefaultOptions(OptionsResolverInterface $resolver)
{

    $resolver->setDefaults(
        array(
            'class'=> 'CmComunBundle:Comun\Nomenclador',
            'code'          => null,                
        )
    );
}


public function getParent()
{
    return 'entity';
}

I'm thinking about use query_builder option, but I don't know how to pass code option to setDefaultOptions method, I don't access to $options array here.

public function setDefaultOptions(OptionsResolverInterface $resolver)
{
        $resolver->setDefaults(
        array(
            'class'=> 'CmComunBundle:Comun\Nomenclador',
            'code'          => null,
            'query_builder' => function(\Doctrine\ORM\EntityRepository $er) use ($options['code']) {
               return $er->createQueryBuilder('c')
                    ->where('c.parent_code = :code')
                    ->orderBy('c.name', 'ASC')
                    ->setParameter('code', $options['code']);;
            }
        )
    );
);
like image 734
smoreno Avatar asked Dec 09 '22 19:12

smoreno


2 Answers

You almost got it right, but you need to make "query_builder" dependent on the other option "code" by using this special syntax:

use Symfony\Component\OptionsResolver\Options;

$resolver->setDefaults(array(
    'query_builder' => function (Options $options) {
        // return default value of the "query_builder" option
        // you can access $options['code'] here
    },
));

So in your specific example:

public function setDefaultOptions(OptionsResolverInterface $resolver)
{
    $resolver->setDefaults(array(
        'class' => 'CmComunBundle:Comun\Nomenclador',
        'code' => null,
        'query_builder' => function (Options $options) {
            return function(EntityRepository $er) use ($options) {
                return $er->createQueryBuilder('c')
                    ->where('c.parent_code = :code')
                    ->orderBy('c.name', 'ASC')
                    ->setParameter('code', $options['code']);;
            };
        },
    ));
}

This is also documented in the OptionsResolver README.

like image 134
Bernhard Schussek Avatar answered Dec 11 '22 07:12

Bernhard Schussek


You could pass the code value to __construct via dependency injection and store it for later use inside the setDefaultOptions method.

class CategoryType{
    ...
    private $code;
    ...
    public function __construct($code){
        $this->code = $code
    }
    ...
    public function setDefaultOptions(OptionsResolverInterface $resolver){
        $code = $this->code;
        $resolver->setDefaults(
        array(
            'class'=> 'CmComunBundle:Comun\Nomenclador',
            'code'          => null,
            'query_builder' => function(\Doctrine\ORM\EntityRepository $er) use ($code) {
                return $er->createQueryBuilder('c')
                                ->where('c.parent_code = :code')
                                ->orderBy('c.name', 'ASC')
                                ->setParameter('code', $code);
            })
        );
    );
}

and in your configuraion:

bt.form.type.category:
    class: My\MBundle\Form\Type\CategoryType
    tags:
        arguments:
                - some_code_value
        - { name: form.type, alias: choice_category }

Now, I haven't tried this but it feels like it should work this way ;)

Hope this helps!

like image 20
Jovan Perovic Avatar answered Dec 11 '22 09:12

Jovan Perovic