【问题标题】:How to disable a field in edit view using Symfony 2 FormBuilder如何使用 Symfony 2 FormBuilder 在编辑视图中禁用字段
【发布时间】:2013-08-18 22:57:48
【问题描述】:

我使用 Symfony2 FormBuilder 创建了一个表单,我想禁用编辑视图中的一个字段。我实际上是用包装器(display:none)隐藏它,但我想知道是否有更好的方法来做到这一点。我的代码如下所示:

实体类型

public function buildForm(FormBuilderInterface $builder, array $options) {
    $builder->add('fieldToDisabledInEditView');
    // ...

实体控制器

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>
    {# ... #}

【问题讨论】:

  • 我知道这是一个老问题,但意识到 display: none 仍然会以 disabled 不会的形式发送值。所以你可能会删除一些你不想删除的东西。

标签: php forms symfony twig


【解决方案1】:

对于那些在 Symfony 3 中寻找解决方案而不创建单独的表单类型类(用于添加和编辑)并且不使用表单事件的人,您可以定义一个自定义选项并在创建时将其传递给表单:

我在表单类型类中创建了一个默认值为falseis_edit 选项:

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

【讨论】:

  • 使用disabled 有一个主要缺点 - 来自此字段的数据不会发送到服务器,因此可编辑字段中的任何错误都会清除禁用字段中的值。我们切换到attrs['readonly]
【解决方案2】:

我想你会发现你在创建和编辑之间会有其他的不同,尤其是验证组。由于您的控制器知道正在执行哪个操作,因此请考虑创建两个表单类型 EditEntity 和 CreateEntity,然后使用公共基础来最大程度地减少重复代码。 @cheesemackfly 展示了如何向元素添加禁用属性。

当然,您可能会觉得拥有两种形式对于如此简单的差异来说是一种浪费。在这种情况下,向您的类添加一个意图标志并在控制器中设置它

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

通过使用服务,您可以从一种表单类型开始,然后当您最终将其拆分为两个(您会这样做)时,您的控制器仍将像以前一样工作。

还有一件事,假设您使用不同的模板进行编辑/创建,您实际上可以直接在 twig 中设置 disabled 属性。所以根本没有代码更改。

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

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

以防万一有人偶然发现这一点,请注意 Symfony 3 不再支持让一个类实现多种表单类型。您基本上必须有单独的表单类型类,即使它们几乎相同。并且永远不要将实例数据添加到您的表单类型中。

【讨论】:

  • 谢谢你们(@cheesemacfly)。现在我只使用{{ form_row(form.yourField, { 'attr':{'disabled':'disabled'} }) }} 部分,但是知道如何在不复制表单的情况下修改表单类型是一件好事。再次感谢,非常感谢:)
【解决方案3】:

这种方法一点也不优雅,但我使用它是因为它很简单:

实体控制器

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

【讨论】:

    【解决方案4】:

    新建(树枝)模板在单独渲染表单字段时不要忘记 {{ 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) }}
    

    【讨论】:

      【解决方案5】:

      这是您可以将事件订阅者用于表单类的典型情况。
      在你的情况下,它应该是:

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

      【讨论】:

        猜你喜欢
        • 2017-12-11
        • 1970-01-01
        • 1970-01-01
        • 2021-12-19
        • 1970-01-01
        • 1970-01-01
        • 2016-02-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多