Kevin
Kevin

Reputation: 5082

Symfony2 - Condition in FormType

I have a class RegisterType for my form:

<?php
class RegisterType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('name');
        $builder->add('price');        
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\Register'
        ));
    }

    public function getName()
    {
        return 'register';
    }
}
?>

The Register Entity has a relation with an Entity called Product

I would like to add this condition to the buildForm function:

<?php
if ($product->getTitle() == 'SuperProduct') {
    $builder->add('amount', 'money', [
        'required' => FALSE,
    ]);
}
?>

If the product title has the value 'SuperProduct' then I add a field in the the form.

But I have no idea about the syntax I have to use to call another Entity value in a FormType.

Thanks in advance for your help.

Upvotes: 0

Views: 3000

Answers (2)

scoolnico
scoolnico

Reputation: 3135

Try something like this:

$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
    $product = $event->getData();
    $form = $event->getForm();

    if ($product->getTitle() == 'SuperProduct') {
        $form->add('name', 'text');
    }
});

And do not forget the specific use

use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents; 

Upvotes: 0

Adambean
Adambean

Reputation: 1161

Ah good you've implemented your FormType as an independent class rather than in a controller, so what I'd do is pass in your product entity as an option to a private variable within your FormType class. I'm not sure what class your product is or the name space it resides in, so you'll have to fill that in.

I've also written this in the expectation that you could have more than one option to pass through in the future, so it'll be useful to other FormType classes you write. Each variable you define in the class scope can be set when you create an instance of the FormType class. Be sure to initialise these variables as false instead of null, or the code in the constructor function won't see them.

<?php
    class RegisterType extends AbstractType
    {
        private $product = false;

        public function __construct(array $options = [])
        {
            foreach ($options as $name => $value) {
                if (isset($this->$name)) {
                    $this->$name => $value;
                }
            }
        }

        public function buildForm(FormBuilderInterface $builder, array $options)
        {
            $builder
                ->add('name')
                ->add('price')
            ;

            if ($this->product && is_a("\Namespace\To\Your\Entity\Called\Product", $this->product)) {
                if ($this->product->getTitle() == 'SuperProduct') {
                    $builder
                        ->add('amount', 'money', [
                            'required' => FALSE,
                        ])
                    ;
                }
            }
        }

        public function configureOptions(OptionsResolver $resolver)
        {
            $resolver->setDefaults(array(
                'data_class' => 'AppBundle\Entity\Register'
            ));
        }

        public function getName()
        {
            return 'register';
        }
    }
?>

That "is_a()" function checks that the product variable passed in through the form type class constructor really is an instance of your product entity, so you can be sure that the getTitle() function exists.

Now when you create a new instance of your RegisterType class, you need to pass through an options array including your product. Two conceptual variable names for you to rename here.

<?php
    $form = $this->createForm(new RegisterType([
        "product" => $instanceOfProductEntityOrNull,
    ]), $theEntityTheFormWillBeHandling);
?>

Upvotes: 1

Related Questions