I created a form with Symfony2 FormBuilder and I want to disabled one of the fields in the edit view. I'm actually hiding it with a wrapper (display:none
) but I was wondering if there's a better way to do this. My code looks like the following:
EntityType
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder->add('fieldToDisabledInEditView');
// ...
EntityController
public function newAction() {
$entity = new Entity;
$form = $this->createForm(new EntityType, $entity);
// ...
}
public function editAction() {
$entity = new Entity;
$form = $this->createForm(new EntityType, $entity);
// ...
}
New (twig) Template
<form>
{{ form_row(form.fieldToDisabledInEditView) }}
{# ... #}
Edit (twig) Template
<form>
<span class="theValueOfTheHiddenField">{{ entity.fieldToDisabledInEditView }}</span>
<div style="display:none">
{{ form_row(form.fieldToDisabledInEditView) }}
</div>
{# ... #}
I think you will find that you will have other differences between create and edit, especially validation groups. Since your controller knows which operation is being done then consider creating two form types EditEntity and CreateEntity and then using a common base to minimize duplicate code. @cheesemackfly shows how to add a disabled attribute to an element.
But of course you probably feel that having two forms is a waste for such a simple difference. In which case, add a intention flag to your class and set it in the controller
class EntityType
{
public function __construct($intention)
{
$this->intention = $intention;
...
// Use $this->intention to tweak the form
}
}
// controller
$form = $this->createForm(new EntityType('create'), $entity);
OR
$form = $this->createForm(new EntityType('edit'), $entity);
If you really want to get into it then use di to inject the intention.
// controller
$formType = $this->get('entity.create.formtype');
OR
$formType = $this->get('entity.edit.formtype');
By using services you can start with just the one formtype and then when you end up splitting it into two (which you will) your controllers will still work as before.
And one more thing, you can actually set the disabled attribute directly in twig assuming you are using different templates for edit/create. So no code changes at all.
{{ form_row(form.yourField, { 'attr':{'disabled':'disabled'} }) }}
======================================================================== Update: 03 March 2016
Just in case anybody stumbles across this, be aware the Symfony 3 no longer supports having one class implement multiple form types. You basically have to have individual form type classes even if they are almost identical. And never add instance data to your form types.
This is the typical case where you can use an event subscriber to a form class.
In your case, it should be as:
// src/Acme/DemoBundle/Form/EventListener/AddfieldToDisabledInEditViewSubscriber.php
namespace Acme\DemoBundle\Form\EventListener;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class AddfieldToDisabledInEditViewSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
// Tells the dispatcher that you want to listen on the form.pre_set_data
// event and that the preSetData method should be called.
return array(FormEvents::PRE_SET_DATA => 'preSetData');
}
public function preSetData(FormEvent $event)
{
$data = $event->getData();
$form = $event->getForm();
// check if the object is "new"
// If you didn't pass any data to the form, the data is "null".
// This should be considered a new object
if (!$data || !$data->getId()) {
$form->add('fieldToDisabledInEditView');
}
else
{
$form->add('fieldToDisabledInEditView', null, array('disabled' => true));
//If PHP >= 5.4
//$form->add('fieldToDisabledInEditView', null, ['disabled' => true]);
}
}
}
And in your form type:
// src/Acme/DemoBundle/Form/Type/EntityType.php
namespace Acme\DemoBundle\Form\Type;
// ...
use Acme\DemoBundle\Form\EventListener\AddfieldToDisabledInEditViewSubscriber;
class EntityType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('your_field');
//...
$builder->addEventSubscriber(new AddfieldToDisabledInEditViewSubscriber());
}
// ...
}
http://symfony.com/doc/current/cookbook/form/dynamic_form_modification.html
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With