【问题标题】:Nullable custom form entity with SymfonySymfony 的可空自定义表单实体
【发布时间】:2016-08-26 14:52:59
【问题描述】:

我的应用程序管理家庭。一个家庭由 1 个或 N 个成员组成。

我希望可以添加一个或两个父级和 0 个或 N 个子级。孩子部分工作正常,但我很难与一两个父母打交道。

这是我的家庭表格类型:

 $builder
        ... many attributes
        ->add('parent1', MemberType::class)
        ->add('parent2', MemberType::class)

Parent 和 parent2 是 OneToOne 关联(Family to member)。会员表格类型:

 $builder
        ->add('firstName', TextType::class, [
            'label' => 'Prénom',
            'constraints' => array(
                new NotBlank(),
                new Length(array('max' => 150))
            )
        ])
        ... many other attributes with choices or not

我想到了一个复选框,如果未选中则将父 2 的字段变灰,但成员值都是必需的。因为那个 SF2 不验证我的表格。

如果我将 required => false 设置为这些字段(在构建器中),那么用户将有可能在不填写所有内容的情况下进行验证(这是我不想要的)。

我想创建以下流程:

  • 我们要么填写 member2 的所有字段以验证表单
  • 要么我们选中一个复选框(单亲)并且不需要任何字段,我的最终 member2 将为 null(或其他解决方案)

【问题讨论】:

    标签: php forms symfony


    【解决方案1】:

    阅读了大量文档后,我在这里找到了我的问题的解决方案:http://symfony.com/doc/current/cookbook/form/dynamic_form_modification.html#cookbook-form-events-submitted-data

    为了使实体不需要,您应该添加事件侦听器并将数据设置为null post submit。

    第一步

    orphanRemoval=true 选项添加到您的属性

    /**
     * @ORM\OneToOne(targetEntity="AppBundle\Entity\Member", orphanRemoval=true, cascade={"persist", "remove"})
     * @ORM\JoinColumn(name="parent2_id", referencedColumnName="id",nullable=true)
     */
    private $parent2;
    

    第二步

    在表单中添加一个新字段,一个未映射的复选框

       $builder
            ->add('parent1', MemberType::class)
            ->add('withParent2', CheckboxType::class, [
                'mapped'            => false,
                'required'          => false,
                'data'              => true
            ])
            ->add('parent2', MemberType::class, [
                'required'          => false
            ])
    

    如果未选中,我们将使用此复选框将 parent2 设置为 null。

    在此旁边,添加您的事件侦听器:

       //this event will set whether or not the checkbox should be checked
       $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
            $form = $event->getForm();
            $family = $event->getData();
    
            if ($family->getId()) {
                $form->add('withParent2', CheckboxType::class, [
                    'mapped'        => false,
                    'required'      => false,
                    'data'          => $family->getParent2() ? true : false
                ]);
            }
        });
    
        //Event when the form is submitted, before database update
        $builder->addEventListener(FormEvents::POST_SUBMIT, function(FormEvent $event) {
    
            //if the checkbox was not checked, it means that there was not a second parent
            $withParent2 = $event->getForm()->get('withParent2')->getData();
            if (!$withParent2) {
    
                // we set this attribute to null, and disable the form validation
                $event->getData()->setParent2(null);
                $event->stopPropagation();
            }
    
        }, 900);
    

    第三步

    我们的表单以这种方式工作正常,唯一剩下的问题是 javascript 验证。

    只需执行一个 jquery 函数,从您的字段中删除所需的属性。

     function toggleParent2Requirement(checked){
            if (!checked) {
                $("[id^=family_parent2]").prop("required", false);
                $("[id^=family_parent2]").attr('disabled', true);
            }
            else {
                $("[id^=family_parent2]").prop("required", true);
                $("[id^=family_parent2]").attr('disabled', false);
            }
        }
    

    在这里,您将 oneToOne 关系设为可选。我唯一不自豪的部分是stopPropagation 部分。这是在文档中,我不知道我们是否只能以更干净的方式禁用该字段的验证。

    【讨论】:

      猜你喜欢
      • 2019-11-04
      • 1970-01-01
      • 1970-01-01
      • 2015-11-01
      • 1970-01-01
      • 2017-02-26
      • 2017-02-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多