2016-05-01 19 views
19

Ứng dụng của tôi quản lý gia đình. Một gia đình bao gồm 1 hoặc N thành viên.Thực thể biểu mẫu tùy chỉnh gọn gàng với Symfony

Tôi muốn có khả năng thêm một hoặc hai cha mẹ và 0 hoặc N con. Các phần trẻ em làm việc tốt, nhưng tôi có một thời gian khó khăn đối phó với 1 hoặc 2 cha mẹ.

Đây là gia đình hình thức loại của tôi:

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

mẹ và parent2 là OneToOne hiệp hội (gia đình thành viên). Loại biểu mẫu thành viên:

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

Tôi nghĩ một hộp kiểm có màu xám trên các trường của phụ huynh 2 nếu không được chọn, nhưng tất cả giá trị thành viên đều được yêu cầu. Do đó, SF2 không xác thực biểu mẫu của tôi.

Nếu tôi đặt yêu cầu => false thành các trường này (trong trình tạo) thì người dùng sẽ có khả năng xác thực mà không cần điền mọi thứ (mà tôi không muốn).

Tôi muốn tạo quy trình sau:

  • Hoặc chúng ta điền vào tất cả các lĩnh vực của member2 để xác nhận các hình thức
  • Hoặc chúng tôi kiểm tra một hộp kiểm (người mẹ độc thân) và không có trường là cần thiết, và member2 cuối cùng của tôi sẽ được null (hoặc dung dịch khác)

Trả lời

7

Sau khi đọc rất nhiều tài liệu, tôi thấy các giải pháp của vấn đề của tôi ở đây: http://symfony.com/doc/current/cookbook/form/dynamic_form_modification.html#cookbook-form-events-submitted-data

Để làm cho một thực thể không cần thiết, bạn nên thêm người nghe sự kiện và thiết lập dữ liệu như gửi bài null.

Bước đầu tiên

Thêm tùy chọn orphanRemoval=true đến thuộc tính của bạn

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

Thứ hai bước

Thêm một lĩnh vực mới để hình của bạn, một hộp kiểm không ánh xạ

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

Chúng tôi sẽ sử dụng hộp kiểm này để đặt parent2 thành null nếu không được chọn.

Tiếp đó, thêm người nghe sự kiện của bạn:

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

bước thứ ba

hình thức của chúng tôi đang làm việc tốt theo cách này, vấn đề duy nhất còn lại là xác minh javascript.

Chỉ cần thực hiện một chức năng jquery để xóa thuộc tính bắt buộc khỏi các trường của bạn.

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

Ở đây bạn tạo một mối quan hệ OneToOne tùy chọn. Phần duy nhất mà tôi không tự hào là phần stopPropagation. Đây là tài liệu hướng dẫn và tôi không biết liệu chúng tôi chỉ có thể vô hiệu hóa xác minh của trường này một cách rõ ràng hơn hay không.

Các vấn đề liên quan