DEMOS / Live Component

Dependent Form Fields

Unleash the power of form events, thanks to LiveComponent and DynamicForms.

// ... use statements hidden - click to show
use App\Form\MealPlannerForm; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\Form\FormInterface; use Symfony\UX\LiveComponent\Attribute\AsLiveComponent; use Symfony\UX\LiveComponent\ComponentWithFormTrait; use Symfony\UX\LiveComponent\DefaultActionTrait;
 #[AsLiveComponent] class MealPlanner extends AbstractController { use ComponentWithFormTrait; use DefaultActionTrait; protected function instantiateForm(): FormInterface { return $this->createForm(MealPlannerForm::class); } }
{# See src/Form/MealPlannerForm.php for the form magic #} <div {{ attributes }} > {{ form_start(form) }} {{ form_row(form.meal) }} {{ form_row(form.mainFood) }} {% if form.pizzaSize is defined %} {{ form_row(form.pizzaSize) }} {% endif %} {{ form_end(form) }} </div> 
// ... use statements hidden - click to show
use App\Enum\Food; use App\Enum\Meal; use App\Enum\PizzaSize; use App\Model\MealPlan; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\Type\EnumType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; use Symfonycasts\DynamicForms\DependentField; use Symfonycasts\DynamicForms\DynamicFormBuilder;
 class MealPlannerForm extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options): void { /** * Install DynamicFormBuilder:. * * composer require symfonycasts/dynamic-forms */ $builder = new DynamicFormBuilder($builder); $builder ->add('meal', EnumType::class, [ 'class' => Meal::class, 'choice_label' => fn (Meal $meal): string => $meal->getReadable(), 'placeholder' => 'Which meal is it?', 'autocomplete' => true, ]) // see: https://github.com/SymfonyCasts/dynamic-forms ->addDependent('mainFood', 'meal', function (DependentField $field, ?Meal $meal) { $field->add(EnumType::class, [ 'class' => Food::class, 'placeholder' => null === $meal ? 'Select a meal first' : \sprintf('What\'s for %s?', $meal->getReadable()), 'choices' => $meal?->getFoodChoices(), 'choice_label' => fn (Food $food): string => $food->getReadable(), 'disabled' => null === $meal, 'autocomplete' => true, ]); }) ->addDependent('pizzaSize', 'mainFood', function (DependentField $field, ?Food $food) { if (Food::Pizza !== $food) { return; } $field->add(EnumType::class, [ 'class' => PizzaSize::class, 'placeholder' => 'What size pizza?', 'choice_label' => fn (PizzaSize $pizzaSize): string => $pizzaSize->getReadable(), 'required' => true, 'autocomplete' => true, ]); }) ; } public function configureOptions(OptionsResolver $resolver): void { $resolver->setDefaults(['data_class' => MealPlan::class]); } }
Author weaverryan
Published 2022-06-17