简体   繁体   English

具有Symfony的可空自定义表单实体

[英]Nullable custom form entity with Symfony

My application manage families. 我的应用管理家庭。 One family consist of 1 or N members. 一个家庭由1或N名成员组成。

I want the possibility to add one parent or two and 0 or N children. 我想要添加一个父母或两个以及0或N个孩子的可能性。 The children part works fine, but I have a hard time dealing with 1 or 2 parents. 儿童部分工作正常,但我很难与1或2个父母打交道。

Here is my family form type: 这是我的家庭表格类型:

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

Parent and parent2 are OneToOne association (Family to member). Parent和parent2是OneToOne关联(Family to member)。 The member form type : 会员表格类型:

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

I thought of a checkbox that grey out the fields of the parent 2 if unchecked, but the member values are all required. 我想到了一个复选框,如果未选中,则会将父2的字段变灰,但成员值都是必需的。 Because of that SF2 does not validate my form. 因为SF2不验证我的表格。

If I set required => false to these fields (in the builder) then the user will have the possibility to validate without filling everything (which I don't want). 如果我将required => false设置为这些字段(在构建器中),那么用户将有可能在不填充所有内容的情况下进行验证(我不想要)。

I'd like to create the following process : 我想创建以下过程:

  • Either we fill all the fields of the member2 in order to validate the form 我们要么填充member2的所有字段以验证表单
  • Either we check a checkbox (single parent) and no field is required, and my final member2 will be null (or another solution) 要么我们检查一个复选框(单个父级),不需要任何字段,我的最后一个成员2将为null(或另一个解决方案)

After reading a lot of documentation, I found the solution of my problem here : http://symfony.com/doc/current/cookbook/form/dynamic_form_modification.html#cookbook-form-events-submitted-data 在阅读了大量文档后,我在这里找到了我的问题的解决方案: http//symfony.com/doc/current/cookbook/form/dynamic_form_modification.html#cookbook-form-events-submitted-data

In order to make an entity not required, you ought to add events listener and set the data as null post submit. 为了使实体不是必需的,您应该添加事件监听器并将数据设置为null post submit。

First step 第一步

Add the orphanRemoval=true option to your attribute orphanRemoval=true选项添加到属性中

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

Second step 第二步

Add a new field to your form, a not mapped checkbox 在表单中添加一个新字段,一个未映射的复选框

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

We'll use this checkbox to set the parent2 to null if not checked. 如果没有选中,我们将使用此复选框将parent2设置为null。

Next to this, add your event listeners : 在此旁边,添加您的事件侦听器:

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

Third step 第三步

Our form is working fine this way, the only problem left is the javascript verification. 我们的表单工作正常,唯一的问题是javascript验证。

Just do a jquery function that remove the required attribute from your fields. 只需执行一个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);
        }
    }

Here you make a oneToOne relation optional. 在这里,您可以选择oneToOne关系。 The only part that I'm not proud is the stopPropagation part. 我不自豪的唯一部分是stopPropagation部分。 This was in the documentation, and I don't know if we can only disable this field's verification in a more clean way. 这是在文档中,我不知道我们是否只能以更干净的方式禁用此字段的验证。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM