user4923309
user4923309

Reputation:

How to disable fields in a symfony-form after submitting and validating the data?

I have the following problem: I create a form, which has a select field and different text fields. When the select field has a certain value, than some text fields should be disabled. So I have JavaScript code, which handles the onchange event on my select field, and then disables/enables the text fields. And I have some PHP logic, which disables the text fields initially depending on the value which is retrieved from the database. This all works. The problem is, that when I validate my form, and I have an validation-error, I don’t know, how to disable my text fields (without using JavaScript) when I render the validated form again. Because in my validation, I setup an fresh and empty entity, then I create the form based on this entity, and then I handle the request. So in the moment of creating the form, I don’t have the values, which I need to determine if the text fields should be disabled or enabled initally.

So the question is, how do I disable some form fields after handling the validation?

Here is some pseudo-code with the problem pointed out in the comments

// create the form object depending on the form entity
private function createForm($formEntity) {
    $attributes = [];
    if ($formEntity->getType() === 'x') {
        // disable fields if type === 'x'
        $attributes = ['disabled' => 'disabled'];
    }

    $form = $this->createFormBuilder($task)
        ->add('type', ChoiceType::class)
        ->add('fieldA', TextType::class, ['attr' => $attributes])
        ->add('fieldB', TextType::class, ['attr' => $attributes])
        ->add('save', SubmitType::class, ['label' => 'Create Task'])
        ->getForm();

    return $form;
}

// action to just view the form
public function detailsAction($id) {
    $databaseEntity = $service->get(id);
    $formEntity = FormEntity::fromDatabaseEntity();

    // in this case, the $formEntity has the values from the database
    // so inside the createForm, the fields can be disabled/enabled
    $form = $this->createForm($formEntity);

    // when I render the form, the fields are disabled initially
    return render('views/details.twig.html', ['form' => $form->createView()]);
}

// action which handles the submit of the form, and render the form with validation constraints, if there are some
public function handleSubmitAction($id) {
    $formEntity = new FormEntity();

    // in this case, the $formEntity is empty
    // so inside the createForm, the fields can not be disabled/enabled
    $form = $this->createForm($formEntity);
    $form->handleRequest($request);

    if ($form->isSubmitted() && $form->isValid()) {
        return $this->redirectToRoute('task_success');
    }

    // when I render the form, the fields are not disabled initially
    return render('views/details.twig.html', ['form' => $form->createView()]);
}

Upvotes: 1

Views: 4687

Answers (1)

Ludo
Ludo

Reputation: 512

You need to modify your form before submit, based on request data you get. This can be done before the request data gets applied to form during submit by using PRE_SUBMIT method.

private function createForm($formEntity) {
    $attributes = [];
    if ($formEntity->getType() === 'x') {
        // disable fields if type === 'x'
        $attributes = ['disabled' => 'disabled'];
    }

    $form = $this->createFormBuilder($formEntity)
        ->add('type', ChoiceType::class)
        ->add('save', SubmitType::class, ['label' => 'Create Task'])
        ->add('fieldA', TextType::class, ['attr' => $attributes]);
        ->add('fieldB', TextType::class, ['attr' => $attributes]);
        ->addEventListener(FormEvents::PRE_SUBMIT, function(FormEvent $event) {
            $attributes = [];
            if ($event->getData()['type'] === 'x') {
              $attributes = ['disabled' => 'disabled'];
            }
            $form = $event->getForm();

            $dataA = $form->get('fieldA')->getData();
            $dataB = $form->get('fieldB')->getData();
            $form->remove('fieldA');
            $form->remove('fieldB');
            $form->add('fieldA', TextType::class, ['attr' => $attributes]);
            $form->add('fieldB', TextType::class, ['attr' => $attributes]);
            $form->get('fieldA')->setData($dataA);
            $form->get('fieldB')->setData($dataB);
        })
        ->getForm();

    return $form;
}

https://symfony.com/doc/current/form/events.html

And you should separate your form creation to separate FormType and Handler classes.

Upvotes: 1

Related Questions