web-dev-qa-db-ja.com

Symfony 2 FormBuilderを使用して編集ビューでフィールドを無効にする方法

Symfony2 FormBuilderでフォームを作成し、編集ビューのフィールドの1つを無効にしたい。私は実際にラッパーで隠しています(display:none)しかし、私はこれを行うためのより良い方法があるかどうか疑問に思っていました。私のコードは次のようになります。

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

新しい(小枝)テンプレート

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

テンプレートの編集(小枝)

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

作成と編集、特に検証グループには他にも違いがあることがわかると思います。コントローラーはどの操作が行われているかを知っているので、EditEntityとCreateEntityの2つのフォームタイプを作成し、共通ベースを使用して重複コードを最小限に抑えることを検討してください。 @cheesemackflyは、無効な属性を要素に追加する方法を示しています。

しかし、もちろん、2つのフォームを持つことは、このような単純な違いの無駄だと感じるでしょう。その場合、意図フラグをクラスに追加し、コントローラーに設定します

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

あなたが本当にそれに入りたいなら、diを使って意図を注入してください。

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

サービスを使用することで、1つのフォームタイプのみで開始し、それを2つに分割した場合(これを行う)、コントローラーは以前と同じように機能します。

そしてもう1つ、実際にtwigでdisabled属性を直接設定することができます。編集/作成に別のテンプレートを使用していると仮定すると、コードはまったく変更されません。

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

================================================= ======================= 2016年3月3日更新

誰かがこれに遭遇した場合に備えて、Symfony 3は1つのクラスが複数のフォームタイプを実装することをサポートしなくなったことに注意してください。基本的には、ほとんど同じであっても、個々のフォームタイプクラスが必要です。また、フォームタイプにインスタンスデータを追加しないでください。

26
Cerad

これは、フォームクラスのイベントサブスクライバーを使用できる典型的なケースです。
あなたの場合、次のようになります。

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

そして、あなたのフォームタイプで:

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

16
cheesemacfly

このアプローチはまったくエレガントではありませんが、単純なので使用します。

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

個別のフォームタイプクラス(追加と編集の両方)を作成せず、フォームイベントを使用せずにSymfony 3でソリューションを探している場合は、カスタムオプションを定義し、作成時にフォームに渡すことができます。

フォームタイプクラスにis_editオプションをデフォルト値falseで作成しました:

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

このオプションには、同じクラスのbuildFormメソッドの$options配列を使用してアクセスできます。

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

最後に、フォームの作成時にデフォルト値を渡すことにより、デフォルト値をオーバーライドできます。

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

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

3
Egon Olieux

新規(小枝)テンプレートフォームフィールドを個別にレンダリングする際に{{form_row(form._token)}}を忘れないでください

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

編集(小枝)テンプレート {{form_row(form.fieldToDisabledInEditView)}}をレンダリングせず、トークンを忘れないでください。

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