2013-08-16 12 views
16

Ich habe ein Formular mit Symfony2 FormBuilder erstellt und möchte eines der Felder in der Bearbeitungsansicht deaktivieren. Ich verstecke es tatsächlich mit einem Wrapper (display:none), aber ich frage mich, ob es einen besseren Weg gibt, dies zu tun. Mein Code sieht wie folgt aus:So deaktivieren Sie ein Feld in der Bearbeitungsansicht mit 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); 
    // ... 
} 

Neu (Zweig) Vorlage

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

Edit (Zweig) Template

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

Ich weiß, das ist eine alte Frage, aber erkennen, dass Anzeige: keiner sendet immer noch den Wert in der Form, wo deaktiviert wird nicht. Sie könnten also Dinge löschen, die Sie nicht möchten. – shokora

Antwort

24

Ich denke, werden Sie feststellen, dass Sie andere Unterschiede zwischen schaffen haben und bearbeiten, insbesondere Validierungsgruppen. Da Ihr Controller weiß, welche Operation ausgeführt wird, sollten Sie die beiden Formulartypen EditEntity und CreateEntity erstellen und dann eine gemeinsame Basis verwenden, um doppelten Code zu minimieren. @cheesemackfly zeigt, wie ein deaktiviertes Attribut zu einem Element hinzugefügt wird.

Aber natürlich haben Sie wahrscheinlich das Gefühl, dass zwei Formen für solch einen einfachen Unterschied eine Verschwendung sind. In diesem Fall eine Absicht Flagge Ihre Klasse hinzufügen und es in der Steuerung

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

Wenn Sie wirklich wollen in sie dann di verwenden, um die Absicht zu injizieren.

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

Durch Dienste verwenden, können Sie nur mit dem einem Formulartyp beginnen und dann, wenn Sie es in zwei aufzuteilen am Ende (die Sie) Ihre Controller nach wie vor funktionieren.

Und noch eine Sache, können Sie das deaktivierte Attribut direkt in Zweig setzen, vorausgesetzt, Sie verwenden verschiedene Vorlagen zum Bearbeiten/Erstellen. Also ändert sich überhaupt kein Code.

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

=========================================== ========================== Update: 03. März 2016

Nur für den Fall, dass jemand darüber stolpert, beachten Sie die Symfony 3 unterstützt nicht mehr, dass eine Klasse mehrere Formulartypen implementiert. Sie müssen grundsätzlich individuelle Formulartypklassen haben, auch wenn sie fast identisch sind. Fügen Sie niemals Instanzdaten zu Ihren Formulartypen hinzu.

+0

Danke euch beiden (@cheesemacfly). Für jetzt nehme ich nur den '{{form_row (form.yourField, {'attr': {'disabled': 'disabled'}})}}' Teil, aber es ist gut zu wissen, wie man den Formulartyp ändert ohne die Formulare zu duplizieren. Danke nochmal, sehr geschätzt :) – viarnes

16

Dies ist der typische Fall, in dem Sie ein Ereignis Teilnehmer zu einer Formularklasse verwenden können.
In Ihrem Fall sollte es sein wie:

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

Und in Ihrem Formulartyp:

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

Neu (Zweig) Template Vergessen Sie nicht, {{form_row (form._token)}} wenn individualy Formularfelder Rendering

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

Edit (Zweig) Template Nur nicht machen nicht {{form_row (form.fieldToDisabledInEditView)}} und Token nicht vergessen.

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

Dieser Ansatz ist durchaus nicht elegant, aber ich benutze es, weil ist einfach:

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

Für die Suche nach einer Lösung in Symfony 3 ohne die Schaffung separaten Formulartypen suchen Klassen (für Hinzufügen und Bearbeiten) und ohne Verwendung von Formularereignissen können Sie eine benutzerdefinierte Option definieren und beim Erstellen an das Formular übergeben:

Ich habe eine is_edit Option mit Standardwert false in der Typklasse Form:

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

Sie diese Option, um die $options Array in der buildForm Methode der gleichen Klasse zugreifen kann:

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

Schließlich Sie können den Standardwert überschreiben, indem Sie ihn bei der Formularerstellung übergeben:

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

Verwandte Themen