gggg
gggg

Reputation: 323

Symfony2: How to disable form field on edit

How can I disable form's name field, if the name of the object is, for example, 'Default'? So users cannot change name for 'Default' object, but can for any other object?

This is what I already have:

ObjectType

     public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('name','text', array('required' => true))
        ->add('description', 'textarea', array('required' => false))
        ->add('type', 'choice', array('choices' => array(
            Object::TYPE_PUBLIC => 'Public',
            Object::TYPE_PRIVATE => 'Private',
        ),
        ));
}

Edit action

/**
 * @Route("/edit/{id}", name="edit_object")
 * @ParamConverter("object", class="ObjectBundle:Object")
 * @Template()
 */
public function editAction(Object $object, Request $request)
{
    $form = $this->createForm(new ObjectType(), $object, array(
        'action' => $this->generateUrl('edit_object',['id' => $object->getId()]),
        'method' => 'POST'));

    $form->handleRequest($request);

    if ($form->isValid() && $form->isSubmitted()) {

        $em = $this->getDoctrine()->getManager();
        $em->persist($object);
        $em->flush();

        return $this->render('@Object/Object/list.html.twig', array(
            'object' => $object));
    }
    return array('collection'=>$collection, 'form' => $form->createView());
}

Upvotes: 2

Views: 2738

Answers (1)

Jason Roman
Jason Roman

Reputation: 8276

A real simple way is to pass a value to the constructor of the form with a flag on if you are editing. So your form type would be:

class ObjectType extends AbstractType
{
    private $isEdit;

    public function __construct($isEdit = false)
    {
        $this->isEdit = $isEdit;
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('description', 'textarea', array('required' => false))
            ->add('type', 'choice', array('choices' => array(
                Object::TYPE_PUBLIC => 'Public',
                Object::TYPE_PRIVATE => 'Private',
            ),
        ));

        if (!$editMode) {
            $builder->add('name','text', array('required' => true));
        }
    }
}

Then in your controller:

public function editAction(Object $object, Request $request)
{
    $form = $this->createForm(new ObjectType($isEdit = true), $object, array(
        'action' => $this->generateUrl('edit_object',['id' => $object->getId()]),
        'method' => 'POST'
    ));
    //...
}

For the createForm on creating a new, you could just pass new ObjectType() and leave off the parameter since it is defaulted to false in this case.


Another method would be to build your form based on the entity you are passing to it, aka FormEvents. If it already contains a value for the id, you could simply not add the name field to the form:

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('description', 'textarea', array('required' => false))
        ->add('type', 'choice', array('choices' => array(
            Object::TYPE_PUBLIC => 'Public',
            Object::TYPE_PRIVATE => 'Private',
        ),
    ));

    $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
        $object= $event->getData();
        $form = $event->getForm();

        if (!$object || null === $object->getId()) {
            $form->add('name','text', array('required' => true));
        }
    });

The exact use case I just gave is specifically documented in Symfony's book

Upvotes: 3

Related Questions