paratassi
paratassi

Reputation: 126

How to dynamically disable every field but the submit button in a Symfony form

It's my understanding that the best practice regarding forms in Symfony is to reuse as much code as you can (well, it's probably best practice in general). I've set up a bunch of actions to edit or create an entity, and both actions use the same form class and the same twig template. Now I have to make a delete form for that entity.

I want to reuse the template I used to create or edit the entity, but this time every field will be disabled. This way the user will see the content of the entity, but won't be confused by the ability to edit the field (it must be clear that by clicking the submit button everything will be deleted, not saved).

Right now that's the form class:

// AppBundle/Controller/DeleteEntityController.php
// ...
class TermType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('term', TextType::class, array('label' => 'Term'));
        $builder->add('definition', TextareaType::class, array('label' => 'Definition'));
        $builder->add('visibility_status', ChoiceType::class, array(
                'label' => 'Visibility',
                'choices' => array(
                    'Visible' => true,
                    'Invisible' => false
                ),
            ));
        $builder->add('page', EntityType::class, array(
                'label' => 'Page',
                'class' => 'AppBundle:Page',
                'query_builder' => function (PageRepository $er) {
                        return $er->getPageByType('Glossary');
                },
                'choice_label' => 'title'
            ));
        $builder->add('submit', SubmitType::class, array(
            'label' => 'Submit'
        ));
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => Term::class,
        ));
    }
}

The first thing I tried was to call the form and set disabled as true ($form = $this->createForm(TermType::class, $term, array('disabled' => true));), but that option disables everything, included the submit button. So I explicitly enabled the submit button thinking it would have overridden the option passed to createForm:

// AppBundle/Form/TermType.php
// ...
$builder->add('submit', SubmitType::class, array(
            'label' => 'Submit',
            'disabled' => false
        ));
// ...

But it didn't work. The only alternative I can think of is passing a custom option and set the disabled option in every field but the submit button with that value. Something along these lines:

// AppBundle/Controller/DeleteEntityController.php
// ...
$form = $this->createForm(TermType::class, $term, array('is_delete_form' => true));
// ...

and

// AppBundle/Form/TermType.php
// ...
$builder->add('submit', SubmitType::class, array(
        'label' => 'Submit',
        'disabled' => $options['is_delete_form']
    ));
// ...

What's the best practice in this case? Should I disable the fields inside the template, or should it be done from the form class?

Upvotes: 2

Views: 3632

Answers (2)

JustBee
JustBee

Reputation: 11

Your issue is interesting whether you only want to use only one form to set up the edit, create and delete views. For my part, I use to generate the crud of the class to gain some time. You directly get the edit/create/delete form, functions, and views of the class that you can tailor to your needs afterward.

You can draw one's inspiration from the method they use to only get one form once the crud is generated:

You can have the method to generate it easily here: http://symfony.com/doc/current/bundles/SensioGeneratorBundle/commands/generate_doctrine_crud.html

It does not really answer your question, but it may help for another time ;)

Upvotes: 0

Thai Duong Tran
Thai Duong Tran

Reputation: 2522

it's is a good question and your solution is also a sensible one. Just remember that if you go with an additional option, it's always good to set a default value for it in configureOptions function:

public function configureOptions(OptionsResolver $resolver)
{
    $resolver->setDefaults(array(
        'data_class' => Term::class,
        // Additional option default should be defined here
    ));
}

However, if you are searching for best practice: the suggestion from Symfony is separating the button from the form class or controller (if you define your form in controller). It gives developer more flexibility and make handling the form much easier. You can find what Symfony architect say about it here: http://symfony.com/doc/current/best_practices/forms.html#form-button-configuration.

Upvotes: 2

Related Questions