0

I have a form that I want to edit based on the errors occurred during its validation but when I try to delete a field I get the exception "AlreadySubmittedException".

How to delete a field from my form after the submit?

$form = $this->createForm(MyForm::class);
$removeTheField=true;

if ($request->getMethod() == 'POST') {
    $form->handleRequest($request);

    if ($form->isValid()) {
        // Send form data to an API and get api errors
        // if api responds with some error
            $removeTheField = false;
        // endif
    }
}

if(removeTheField)) {
    $form->remove('my_field'); // throw AlreadySubmittedException
}

One solution that I am considering but which I do not like too much would be to recreate the form again with the data of the previous one and the field in less.

Alex83690
  • 758
  • 9
  • 30
  • 1
    Why would you remove a field after submission of the form? – Cid Nov 19 '18 at 14:57
  • I have a form that can ask the user for an extra code to override an error that can happen (this code grants additional permissions) but this input should not be displayed by default. – Alex83690 Nov 19 '18 at 15:00
  • The opposite behavior is also problematic: Adding the field after I have the expected error also causes the exception. – Alex83690 Nov 19 '18 at 15:06
  • 1
    How about sending the full form to the view but rendering all fields except the admin code the first time and all the second time (you can easily handle it with the controller, e.g. send a flag to the view on validation error) ? (or the other way around if you want all the first time and not this field the second time) – Jules R Nov 19 '18 at 15:08
  • The form_rest will display the field, right? – Alex83690 Nov 19 '18 at 15:09
  • I mean you can manage which fields you render, you're not forced to render all of them https://symfony.com/doc/current/form/rendering.html#rendering-each-field-by-hand – Jules R Nov 19 '18 at 15:11
  • Exact but here is the form_end code : {%- block form_end -%} {%- if not render_rest is defined or render_rest -%} {{ form_rest(form) }} {%- endif -%} {%- endblock form_end -%} However, another solution to the problem: https://stackoverflow.com/questions/10570002/how-to-make-form-rest-not-display-a-field-with-symfony2 – Alex83690 Nov 19 '18 at 15:14
  • Your solution in combination with that of the previous comment link works. Pass the variable to the template and then use: {% if i_need_my_field %} {{ form_row(form.my_field) }} {% else %} {% do form.my_field.setRendered %} {% endif %} I invite you to propose an answer so that I can validate it. – Alex83690 Nov 19 '18 at 15:25
  • I think you can solve problem with form events descripted here: https://symfony.com/doc/current/form/events.html#event-listeners – Fabian Schmick Nov 19 '18 at 15:47
  • Jules R I invite you to post an answer from the previous comments. Otherwise I'll post one in a few days. Fabian, I considered using the events but it does not match what I'm looking for. The problem will be the same, I can not add / delete a field even in an event listener. – Alex83690 Nov 19 '18 at 16:01

3 Answers3

1

I think that is not the correct way. So if you know that you have another validation then you should implement your own validation for that field that you can work with the correct value and validate it.

https://symfony.com/doc/current/validation/custom_constraint.html

If you don't need the field then you should remove them or disable the validation for that field.

René Höhle
  • 26,716
  • 22
  • 73
  • 82
  • I need this field but only when an error has occurred: I submitted the form at least once, the input should not appear before. – Alex83690 Nov 19 '18 at 15:03
0

It should be something like this? If the form is submitted you can check for errors and then create another form to render.

if ($request->getMethod() == 'POST') {
    $form->handleRequest($request);

    if ($form->isValid()) {
        // check for errors
        if(removeTheField){
            $the_new_form = $this->createFormBuilder(null)-> ...
            // $the_new_form does not have 'my_field'
            return $this>render('your_twig.html.twig', array('form' => $the_new_form->createView()));
        }
    }
}

In 'your_twig.html.twig' you can check if the form contains or not the 'my_field' avoiding issues with Twig.

SimoBrazz
  • 81
  • 7
  • it misses the twig part with : {% if i_need_my_field %} {{ form_row(form.my_field) }} {% else %} {% do form.my_field.setRendered %} {% endif %} – Alex83690 Nov 19 '18 at 17:28
0

PHP

$form = $this->createForm(MyForm::class);
$removeTheField=true;

if ($request->getMethod() == 'POST') {
    $form->handleRequest($request);

    if ($form->isValid()) {
        // Send form data to an API and get api errors
        // if api responds with some error
            $removeTheField = false;
        // endif
    }
}

return $this->render('template.html.twig', [
    'form' => $form->createView(), 
    'removeTheField' => $removeTheField
]);

Twig

 {% if removeTheField %}
     {% do form.my_field.setRendered %}
 {% else %}
     <div class="col-md-6">
          {{ form_row(form.my_field) }}
      </div>
 {% endif %}
Alex83690
  • 758
  • 9
  • 30