2013-08-16 6 views
16

Ho creato un modulo con Symfony2 FormBuilder e voglio disabilitare uno dei campi nella vista di modifica. In realtà lo nascondo con un wrapper (display:none) ma mi stavo chiedendo se c'è un modo migliore per farlo. Il mio codice è simile al seguente:Come disabilitare un campo in edit view con Symfony 2 FormBuilder

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); 
    // ... 
} 

Nuovo (ramoscello) Template

<form> 
    {{ form_row(form.fieldToDisabledInEditView) }} 
    {# ... #} 

Edit (ramoscello) Template

<form> 
    <span class="theValueOfTheHiddenField">{{ entity.fieldToDisabledInEditView }}</span> 
    <div style="display:none"> 
     {{ form_row(form.fieldToDisabledInEditView) }} 
    </div> 
    {# ... #} 
+0

So che questa è una domanda vecchia ma rendiamo conto che la visualizzazione: nessuno invierà comunque il valore nel modulo in cui non sarà disabilitato. Quindi potresti cancellare alcune cose che non vuoi. – shokora

risposta

24

Penso che troverete che avrete altre differenze tra creare e modifica, in particolare i gruppi di convalida. Poiché il tuo controller sa quale operazione è in corso, considera di creare due tipi di modulo EditEntity e CreateEntity e quindi di utilizzare una base comune per ridurre al minimo il codice duplicato. @cheesemackfly mostra come aggiungere un attributo disabilitato a un elemento.

Ma ovviamente si ha la sensazione che avere due forme sia uno spreco per una differenza così semplice. Nel qual caso, aggiungere una bandierina intenzione di vostra classe e impostarlo nel regolatore

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); 

Se davvero si vuole entrare in esso quindi utilizzare di per iniettare l'intenzione.

// controller 
$formType = $this->get('entity.create.formtype'); 
OR 
$formType = $this->get('entity.edit.formtype'); 

Utilizzando i servizi si può iniziare con solo quella FormType e poi quando si finisce per dividere in due (che sarà) i controller continuerà a funzionare come prima.

E ancora una volta, è possibile impostare l'attributo disabilitato direttamente nella ramoscella assumendo che si stiano utilizzando modelli diversi per la modifica/creazione. Quindi nessun codice cambia affatto.

{{ form_row(form.yourField, { 'attr':{'disabled':'disabled'} }) }} 

=========================================== =============== Aggiornamento: 03 marzo 2016

Nel caso in cui qualcuno si imbattesse in questo, sii consapevole del Symfony 3 non supporta più il fatto che una classe implementa più tipi di moduli. Fondamentalmente devi avere classi di tipi di moduli individuali anche se sono quasi identici. E non aggiungere mai dati di istanza ai tipi di modulo.

+0

Grazie a entrambi (@cheesemacfly). Per ora sto prendendo solo il '{{form_row (form.yourField, {'attr': {'disabled': 'disabled'}})}}' parte, ma è un bene sapere come modificare il tipo di modulo senza duplicare le forme. Grazie ancora, molto apprezzato :) – viarnes

16

Questo è il tipico caso in cui è possibile utilizzare un abbonato evento ad una classe di form.
Nel tuo caso, dovrebbe essere come:

// 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]); 
     } 
    } 
} 

E nel vostro tipo di modulo:

// 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

1

Nuovo (ramoscello) Template Non dimenticate {{form_row (form._token)}} durante il rendering dei campi modulo individualmente

<form> 
    {{ form_row(form.fieldToDisabledInEditView) }} 
    {{ form_row(form.field2) }} 
    {{ form_row(form.field3) }} 
    {# ... #} 
    {{ form_row(form._token) }} 

Edit (ramoscello) Template Proprio non rendere {{form_row (form.fieldToDisabledInEditView)}} e di nuovo non dimenticare il token.

<form> 
    {{ form_row(form.field2) }} 
    {{ form_row(form.field3) }} 
    {# ... #} 
    {{ form_row(form._token) }} 
9

Questo approccio non è elegante a tutti, ma lo uso perché è semplice:

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); 
    $form->remove('fieldToDisabledInEditView');  
    // ... 
} 
2

Per chi cerca una soluzione in Symfony 3 senza creare Tipo modulo separato classi (sia per aggiungere e modificare) e senza utilizzare gli eventi del modulo, è possibile definire un'opzione personalizzata e passarlo al modulo al momento della creazione:

Ho creato un'opzione is_edit con valore di default false nella classe tipo di modulo:

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

È possibile accedere a questa opzione utilizzando la matrice $options nel metodo buildForm della stessa classe:

public function buildForm(FormBuilderInterface $builder, array $options) 
{ 
    $builder->add('someField', TextType::class, array(
     'disabled' => $options['is_edit'] 
    )) 
} 

Infine , è possibile ignorare il valore di default passando sulla creazione di moduli:

$someForm = $this->createForm(
    SomeEntityType::class, 
    $someEntity, 
    array('is_edit' => true) 
); 

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

Problemi correlati