Last active
October 23, 2024 12:23
-
-
Save Raphhh/91a1eae22f76f92c00b806b3644a2a1e to your computer and use it in GitHub Desktop.
Symfony form: set options according to the data
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace AppBundle\Form\EventListener; | |
use Symfony\Component\EventDispatcher\EventSubscriberInterface; | |
use Symfony\Component\Form\FormEvent; | |
use Symfony\Component\Form\FormEvents; | |
class ContextualOptionsFormListener implements EventSubscriberInterface | |
{ | |
/** | |
* @var callable | |
*/ | |
private $callback; | |
/** | |
* The callback will be called for each child of the listened form. | |
* The callback will receive the following params: | |
* - FormEvent $event | |
* - $name name of the child | |
* - array $options the initial options of the child | |
* The callback must return an array with the final options of the child. | |
* | |
* @param callable $callback | |
*/ | |
public function __construct(callable $callback) | |
{ | |
$this->callback = $callback; | |
} | |
/** | |
* @return array The event names to listen to | |
*/ | |
public static function getSubscribedEvents() | |
{ | |
return [ | |
FormEvents::PRE_SET_DATA => 'preSetData', | |
]; | |
} | |
/** | |
* @param FormEvent $event | |
*/ | |
public function preSetData(FormEvent $event) | |
{ | |
$form = $event->getForm(); | |
$data = $event->getData(); | |
if (null === $data) { | |
return; | |
} | |
$children = $form->all(); | |
foreach ($form as $name => $child) { | |
$form->remove($name); | |
} | |
foreach ($children as $name => $child) { | |
$form->add( | |
$name, | |
$child->getConfig()->getType()->getInnerType(), | |
call_user_func($this->callback, $event, $name, $child->getConfig()->getOptions()) | |
); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace AppBundle\Model; | |
class Example | |
{ | |
public $value; | |
public function isDisabled() | |
{ | |
return $this->value === 'disabled'; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace AppBundle\Controller; | |
use Symfony\Bundle\FrameworkBundle\Controller\Controller; | |
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; | |
use AppBundle\Model\Example; | |
use AppBundle\Model\Form\Type\ExampleType; | |
class ExampleController extends Controller | |
{ | |
/** | |
* @Route("/") | |
* @return \Symfony\Component\HttpFoundation\RedirectResponse | |
*/ | |
public function indexAction() | |
{ | |
$example = new Example(); | |
$example->value = 'disabled'; | |
$form = $this->createForm(ExampleType::class, $example); | |
... | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace AppBundle\Form\Type; | |
use Symfony\Component\Form\AbstractType; | |
use AppBundle\Form\EventListener\ContextualOptionsFormListener; | |
use Symfony\Component\Form\FormBuilderInterface; | |
use Symfony\Component\Form\FormEvent; | |
class ExampleType extends AbstractType | |
{ | |
/** | |
* @param FormBuilderInterface $builder | |
* @param array $options | |
*/ | |
public function buildForm(FormBuilderInterface $builder, array $options) | |
{ | |
$builder->add('value'); | |
$builder->addEventSubscriber(new ContextualOptionsFormListener( | |
function (FormEvent $event, $name, array $options) { | |
if ($name === 'value') { | |
//the "value" field will be conditionnaly disabled according to Example instance. | |
$options['disabled'] = $event->getData()->isDisabled(); | |
} | |
return $options; | |
} | |
)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The goal:
You want to set some options conditionnally, according to the data given.
The problem:
The solution here
We loop on each child and reset it with a callback that can modify the options according to the data.