2017-08-16 93 views
5

Próbuję utworzyć formularz adresu z adresem płatności i wysyłki. Po zaznaczeniu pola wyboru na adres wysyłki chcę pominąć walidację formularza na tym adresie.Wyłącz sprawdzanie poprawności dla typu formularza, jeśli pole wyboru jest zaznaczone w Symfony

Utworzono poniższy typ formularza z opcją przełączania, która wyświetli pole wyboru i zajmie się nim, ale formularz jest nadal sprawdzany, nawet jeśli jest zaznaczony.

Symfony ma documentation on how to implement such a form, i mimo że prawie mam dokładnie ten sam kod, sprawdzanie poprawności nie jest wyłączane. Nie używam grup sprawdzania poprawności, więc po prostu wyłączam domyślną grupę, aby wyłączyć sprawdzanie poprawności w encji.

AddressType buduje formę dla klasy Address (która ma ograniczenia adnotacji w pewnych dziedzinach, takich jak NotBlank i Callback).

class AddressType extends AbstractType 
{ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     if ($options["toggle"]) { 
      $builder->add("toggle", CheckboxType::class, [ 
       "mapped" => false, 
       "required" => false, 
       "label" => $options["toggle"] 
      ]); 
     } 

     $builder 
      ->add("name", TextType::class, [ 
       "required" => !$options["toggle"] 
      ]) 
      ->add("address", TextType::class, [ 
       "required" => !$options["toggle"] 
      ]) 
      ->add("zipcode", TextType::class, [ 
       "label" => "Postcode", 
       "required" => !$options["toggle"] 
      ]) 
      ->add("city", TextType::class, [ 
       "required" => !$options["toggle"] 
      ]) 
      ->add("countryCode", ChoiceType::class, [ 
       "choices" => Address::COUNTRY_CODES 
      ]); 
    } 

    public function configureOptions(OptionsResolver $resolver) 
    { 
     $resolver->setDefaults([ 
      "toggle" => false, 
      "data_class" => Address::class, 
      "validation_groups" => function(FormInterface $form) { 
       if ($form->has("toggle") && $form->get("toggle")->getData() === true) { 
        return []; 
       } 

       return ["Default"]; 
      } 
     ]); 

     $resolver->setAllowedTypes("toggle", ["bool", "string"]); 
    } 
} 

używam rodzaj takiego:

$addressForm = $this 
    ->createFormBuilder([ 
     "paymentAddress" => $paymentAddress, 
     "shippingAddress" => $shippingAddress 
    ]) 
    ->add("paymentAddress", AddressType::class, [ 
     "label" => false 
    ]) 
    ->add("shippingAddress", AddressType::class, [ 
     "label" => false, 
     "toggle" => "Use payment address" 
    ]) 
    ->add("submit", SubmitType::class, [ 
    ]) 
    ->getForm(); 

Przyjeżdżam nad tym przez kilka godzin, ale teraz nie jestem w stanie wydedukować dlaczego walidacja nie jest wyłączony, a ja nie chcę zgniatać formy nad tym małym szczegółem.

Dlaczego sprawdzanie poprawności dla AddressType nie jest wyłączone przez zamknięcie w configureOptions? Jeśli po prostu nie jest tak, jak to działa, jakie byłoby lepsze rozwiązanie w przypadku częściowego wyłączenia walidacji w uporządkowany sposób?

EDYCJA: Nawet jeśli ustawienie "validation_groups" => false w ustawieniach domyślnych, dzieci utworzone w programie budującym lub w użyciu formularza, sprawdzanie poprawności będzie nadal. To nie ma nic wspólnego z zamknięciem. Każdy zasób online, w tym własny zasób Symfony, oświadcza, że ​​powinien działać ...

Odpowiedz

2

[...] więc wyłączam domyślną grupę, aby wyłączyć sprawdzanie poprawności w encji.

Zakładając, że Address właściwości & ograniczenia wyglądać następująco:

/** 
* @Assert\NotBlank() 
*/ 
private $name; 

// etc. 

W „weryfikator” zakłada, że ​​właściwości te będą oceniane z Default grupy, bo zawsze uważa pusty validation_groups (np return [];) jako ['Default'] (dlatego sprawdzanie poprawności nie jest wyłączane, gdy jest zaznaczone):

https://symfony.com/doc/current/validation/groups.html: Jeśli nie określono żadnych grup, zostaną zastosowane wszystkie wiązania należące do grupy Default.

Rozwiązaniem zrealizować częściowo wyłączyć sprawdzanie w uporządkowany sposób

powinny istnieć wiele sposobów, aby to osiągnąć, ale pokażę dwa z nich:

  1. Jeśli żadna data_class jest ustawiona na formę główną, a następnie dostępna jest grupa Form do sprawdzania poprawności tylko tego poziomu:

    $addressForm = $this 
        ->createFormBuilder([...], [ 
         'validation_groups' => 'Form', // <--- set 
        ]) 
    

    Następnie w configureOptions metody, ustaw Address grupę jako domyślne i Form grupę jeśli „przełączać” jest zaznaczone, dodaje również Valid() ograniczenie walidacji kaskady:

    public function configureOptions(OptionsResolver $resolver) 
    { 
        $resolver->setDefaults([ 
         // ... 
         "validation_groups" => function(FormInterface $form) { 
          if ($form->has("toggle") && $form->get("toggle")->getData() === true) { 
           return ['Form']; // <--- set 
          } 
    
          return ['Address']; // <--- set 
         }, 
         'constraints' => [new Assert\Valid()], // <--- set 
        ]); 
    } 
    

    Oznacza to, że na przedstawienia z przełącznik off: Form i Address grupy są stosowane do pól adresowych, w przeciwnym razie stosowana jest tylko grupa .

  2. (Innym sposobem) W Address klasy add „Wymagane” grupa do wszystkich ograniczeń, unika zweryfikować te właściwości z Default grupy:

    /** 
    * @Assert\NotBlank(groups={"Required"}) // <--- set 
    */ 
    private $name; 
    
    // etc. 
    

    Następnie w configureOptions metody ustawić Required jako grupy domyślnej i Default jeżeli przełącznik jest sprawdzana:

    public function configureOptions(OptionsResolver $resolver) 
    { 
        $resolver->setDefaults([ 
         // ... 
         "validation_groups" => function(FormInterface $form) { 
          if ($form->has("toggle") && $form->get("toggle")->getData() === true) { 
           return ['Default']; // <--- set 
          } 
    
          return ['Required']; // <--- set 
         }, 
         'constraints' => [new Assert\Valid()], // <--- set 
        ]); 
    } 
    

    W tym przypadku, na przedstawienia z przełącznik off: Default i Required grup jest stosowanych do pól adresowych, w innym przypadku tylko grupa Default, pomijając w ten sposób wymagane pola.

zagnieżdżone formy, które zawierają obiekty odłączone od obiektu głównego może być weryfikowane poprzez ustawienie ograniczenia, new Valid().

+1

Dziękujemy za szczegółową odpowiedź. Próbowałem już dodawać grupy do wszystkich ograniczeń i domyślnie zwracać te grupy z zamykania validation_groups. To, czego mi brakowało, było obowiązującym ograniczeniem. Nie przyszło mi do głowy, że dodane pola staną się dziećmi typu AddressType i dlatego będą wymagały ograniczenia. – Villermen