Add a required form field based on submitted data in Symfony2

813 Views Asked by At

I have a form with a status select. If a certain status is selected and the form is submitted it should reload and require an additional field.

I have read Dynamic generation for submitted Forms and almost every other post on the internet and about this topic and tried different event combinations (and got different errors) but I still struggle to make this to work correctly.

This is what I have so far:

FormType

private function addProcessAfterField(FormInterface $form)
{
    $form->add('processAfterDate', 'date', array('required' => true));
}


public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder->add('status', 'entity', array(
        'class' => 'Acme\Bundle\ApplicationBundle\Entity\LeadStatusCode',
        'choices' => $this->allowedTypes
    ));

    $builder->addEventListener(FormEvents::PRE_SET_DATA, function(FormEvent $event){

        $form = $event->getForm();
        $data = $event->getData();

        if ($data->getStatus()->getId() == LeadStatusCode::INTERESTED_LATER) {
            $this->addProcessAfterField($form);
        }
    });

    $builder->get('status')->addEventListener(FormEvents::POST_SUBMIT, function(FormEvent $event){
        $data = $event->getData();
        if ($data == LeadStatusCode::INTERESTED_LATER && !$event->getForm()->getParent()->getData()->getProcessAfterDate()) {
            $this->addProcessAfterField($event->getForm()->getParent());
        }
    });

    $builder->add('comment', 'textarea', array('mapped' => false));
    $builder->add('Update', 'submit');
}

Error:

ContextErrorException: Catchable Fatal Error: Argument 1 passed to Proxies\__CG__\Acme\Bundle\ApplicationBundle\Entity\Lead::setProcessAfterDate() must be an instance of DateTime, null given, called in /var/www/application.dev/vendor/symfony/symfony/src/Symfony/Component/PropertyAccess/PropertyAccessor.php on line 360 and defined in /var/www/application.dev/app/cache/dev/doctrine/orm/Proxies/__CG__AcmeBundleApplicationBundleEntityLead.php line 447

As already mentioned I tried different event combinations, one was almost working but then the date was never persisted to the entity so I added the \DateTime type-hint to the setProcessAfterDate() method. I am not sure if I don`t understand the event system correctly or if the error lies somewhere else.

1

There are 1 best solutions below

1
Bartłomiej Wach On

Well, it might not be the best way to solve it, but to make long story short:

$form->handleRequest($request);

if($form->isValid()) // check if the basic version of the form is ok
{
     $form = $this->createForm(new XXXXForm(), $form->getData()); // you recreate the form with the data that was submitted, so you rebuild the form with new data

     if($form->isValid())
     {
           // ok
     }



  // not ok
}

Then inside buildForm function, you base the "required" attribute value of fields based on what you want:

'required' => $this->getCheckRequired($options)


private function getCheckRequired($options) // checks whether field should be required based on data bound to the form
{
  if($options && isset($options['data'])
  {

    switch $options['data']->getStatus():
       // whatever

    ;
  }

return false;

}  

As I said, this is not the best solution, and it doesn't fix your approach, but rather proposes a different one, but it does the job