Reputation: 11
I have a simple form:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', null, ['required' => true])
->add('doYouWant', ChoiceType::class, ['choices' => ['no' => 'no', 'yes' => 'yes']])
->add('type')
;
}
I would like the user after the selection doYouWant to "yes" to have a mandatory "type" option, so I am trying:
$builder->addEventListener(
FormEvents::PRE_SUBMIT,
function (FormEvent $event) use ($builder) {
$data = $event->getForm()->getData();
if ($data['doYouWant'] == 'yes') {
$builder->add('type', null, ['required' => true]);
}
}
);
But it does not matter...
Upvotes: 1
Views: 1535
Reputation: 1736
I think the simplest way would be to add constraints
to each field from your type, and then, in template, by using jquery you can toggle the visibility of your type field based on the selected value from the dropdown.
# AppBundle/Form/ExampleType.php
$builder
->add('name', null, [
'constraints' => [
new NotBlank(['message' => 'This cannot be empty']),
]
])
->add('doYouWant', ChoiceType::class, [
'placeholder' => 'Select',
'choices' => ['no' => 'No', 'yes' => 'Yes'],
'constraints' => [
new NotBlank(['message' => 'This cannot be empty']),
]
])
->add('type', EmailType::class, [
'constraints' => [
new NotBlank(['message' => 'This cannot be empty']),
new Email([
'message' => "The email '{{ value }}' is not a valid email",
])
]
])
;
I've added the type
field as being of type email, just for testing purposes.
# Controller/DefaultController.php
/**
* @param Request $request
* @Route("/test", name="test")
* @return Response
*/
public function testAction(Request $request) : Response
{
$form = $this->createForm(ExampleType::class);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
dump($form->getData());die;
}
return $this->render('default/test.html.twig', [
'form' => $form->createView(),
]);
}
# default/test.html.twig (assuming you are using bootstrap and jquery)
{% block body %}
<div class="container">
<div class="row">
<div class="col-xs-12">
{{ form_start(form, { attr: { 'novalidate': 'novalidate' } }) }}
<div class="form-group">
{{ form_label(form.name) }}
{{ form_widget(form.name,{ attr:{ class:'form-control' } }) }}
{{ form_errors(form.name) }}
</div>
<div class="form-group">
{{ form_label(form.doYouWant) }}
{{ form_widget(form.doYouWant,{ attr:{ class:'form-control' } }) }}
{{ form_errors(form.doYouWant) }}
</div>
<div class="form-group type hidden">
{{ form_label(form.type) }}
{{ form_widget(form.type,{ attr:{ class:'form-control' } }) }}
{{ form_errors(form.type) }}
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">Send</button>
</div>
{{ form_end(form) }}
</div>
</div>
</div>
{% endblock %}
{% block javascripts %}
<script>
$(document).ready(function(){
$('#appbundle_example_doYouWant').change(function(){
var choice = $(this).val();
if (choice == 'Yes') {
$('.type').removeClass('hidden');
} else {
$('.type').addClass('hidden');
}
});
});
</script>
{% endblock %}
Upvotes: 1
Reputation: 2237
You can use validation groups and put your assertions inside your entity.
And then you can choose validation groups based on the submitted data like so:
https://symfony.com/doc/current/form/data_based_validation.html
How to add assertion on entity:
class MyEntity {
/**
* @Assert\NotBlank(groups={"YourGroup"})
*/
protected $type;
}
Then on your form:
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'validation_groups' => function (FormInterface $form) {
$data = $form->getData();
$want = $data->getDoYouWant();
if ($want) {
return ['YourGroup'];
}
return ['Default'];
},
));
}
Upvotes: 0