2016-09-05 4 views
0

symfony 2.3を使用していますので、明らかにhereという 'allow_extra_fields'オプションは使用できません。フォームのサブスクライバと "このフォームには余分なフィールドを含めてはいけません"エラー

Iメインフォームタイプ、RegistrationStep1UserType有する:

/** 
* Class RegistrationStep1UserType 
* @package Evo\DeclarationBundle\Form\Type 
*/ 
class RegistrationStep1UserType extends AbstractType 
{ 
    /** 
    * @param FormBuilderInterface $builder 
    * @param array $options 
    */ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder 
      ->add('customer', new RegistrationStep1CustomerType(), [ 
       'label' => false, 
       'data_class' => 'Evo\UserBundle\Entity\Customer', 
       'cascade_validation' => true, 
      ]) 
      ->add('declaration', 'evo_declaration_bundle_registration_step1_declaration_type', [ 
       'label' => false, 
       'cascade_validation' => true, 
      ]) 
     ; 
    } 

    /** 
    * @param OptionsResolverInterface $resolver 
    */ 
    public function setDefaultOptions(OptionsResolverInterface $resolver) 
    { 
     $resolver->setDefaults(array(
      'data_class' => 'Evo\UserBundle\Entity\User', 
      'validation_groups' => false, 
     )); 
    } 

    /** 
    * @return string 
    */ 
    public function getName() 
    { 
     return 'evo_declaration_bundle_registration_step1_user_type'; 
    } 
} 

このフォームタイプはサービスとして登録( "宣言" フィールドに)埋め込みフォームタイプ、RegistrationStep1DeclarationTypeを含む:

/** 
* Class RegistrationStep1DeclarationType 
* @package Evo\DeclarationBundle\Form\Type 
*/ 
class RegistrationStep1DeclarationType extends AbstractType 
{ 
    /** 
    * @var EntityManagerInterface 
    */ 
    private $em; 

    /** 
    * @var EventSubscriberInterface 
    */ 
    private $addBirthCountyFieldSubscriber; 

    /** 
    * RegistrationStep1DeclarationType constructor. 
    * @param EntityManagerInterface $em 
    * @param EventSubscriberInterface $addBirthCountyFieldSubscriber 
    */ 
    public function __construct(EntityManagerInterface $em, EventSubscriberInterface $addBirthCountyFieldSubscriber) 
    { 
     $this->em = $em; 
     $this->addBirthCountyFieldSubscriber = $addBirthCountyFieldSubscriber; 
    } 

    /** 
    * @param FormBuilderInterface $builder 
    * @param array $options 
    */ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder 
      ->add('birthLastname', null, [ 
       'label' => 'Nom de naissance', 
       'attr' => [ 
        'required' => true, 
       ], 
      ]) 
      ->add('nationality', 'entity', [ 
       'label' => 'Nationalité', 
       'class' => 'Evo\GeoBundle\Entity\Country', 
       'property' => 'nationalityFr', 
       'attr' => [ 
        'required' => true, 
        'class' => 'selectpicker', 
       ], 
       'preferred_choices' => $this->fillPreferredNationalities(), 
      ]) 
      ->add('birthCountry', 'entity', [ 
       'label' => 'Pays de naissance', 
       'class' => 'Evo\GeoBundle\Entity\Country', 
       'property' => 'nameFr', 
       'empty_value' => '', 
       'empty_data' => null, 
       'attr' => [ 
        'required' => true, 
        'class' => 'trigger-form-modification selectpicker', 
       ], 
       'preferred_choices' => $this->fillPreferredBirthCountries(), 
      ]) 
      ->add('birthCity', null, [ 
       'label' => 'Ville de naissance', 
       'attr' => [ 
        'required' => true, 
       ], 
      ]) 
     ; 

     $builder->get("birthCountry")->addEventSubscriber($this->addBirthCountyFieldSubscriber); 
    } 

    /** 
    * @return array 
    */ 
    private function fillPreferredNationalities() 
    { 
     $nationalities = $this->em->getRepository("EvoGeoBundle:Country")->findBy(["isDefault" => true]); 

     return $nationalities; 
    } 

    /** 
    * @return array|\Evo\GeoBundle\Entity\Country[] 
    */ 
    private function fillPreferredBirthCountries() 
    { 
     $countries = $this->em->getRepository("EvoGeoBundle:Country")->findBy(["isDefault" => true]); 

     return $countries; 
    } 

    /** 
    * @param OptionsResolverInterface $resolver 
    */ 
    public function setDefaultOptions(OptionsResolverInterface $resolver) 
    { 
     $resolver->setDefaults(array(
      'required' => false, 
      'data_class' => 'Evo\DeclarationBundle\Entity\Declaration', 
      'validation_groups' => false, 
     )); 
    } 

    /** 
    * @return string 
    */ 
    public function getName() 
    { 
     return 'evo_declaration_bundle_registration_step1_declaration_type'; 
    } 
} 

をこの埋め込みフォームタイプは、「birthCountry」フィールドにサブスクライバ(EntityManagerの注入が必要なためサービスとしても登録されています)を追加します。

birthCountryの選択リストの値に応じて、追加のフィールド(「birthCounty」と呼ばれる)を動的に追加または削除することを目標にしています(ここでは、2つのフィールドは「birthCountry」と「birthCounty」です)。鑑み

/** 
* Class AddBirthCountyFieldSubscriber 
* @package Evo\CalculatorBundle\Form\EventListener 
*/ 
class AddBirthCountyFieldSubscriber implements EventSubscriberInterface 
{ 
    /** 
    * @var EntityManagerInterface 
    */ 
    private $em; 

    /** 
    * AddBirthCountyFieldSubscriber constructor. 
    * @param EntityManagerInterface $em 
    */ 
    public function __construct(EntityManagerInterface $em) 
    { 
     $this->em = $em; 
    } 

    /** 
    * @return array 
    */ 
    public static function getSubscribedEvents() 
    { 
     return array(
      FormEvents::POST_SET_DATA => 'postSetData', 
      FormEvents::POST_SUBMIT => 'postSubmit', 
     ); 
    } 

    /** 
    * @param FormEvent $event 
    */ 
    public function postSetData(FormEvent $event) 
    { 
     $birthCountry = $event->getData(); 
     $form = $event->getForm()->getParent(); 

     $this->removeConditionalFields($form); 

     if ($birthCountry instanceof Country && true === $birthCountry->getIsDefault()) { 
      $this->addBirthCountyField($form); 
     } 
    } 

    /** 
    * @param FormEvent $event 
    */ 
    public function postSubmit(FormEvent $event) 
    { 
     $birthCountry = $event->getData(); 
     $form = $event->getForm()->getParent(); 

     if (!empty($birthCountry)) { 
      $country = $this->em->getRepository("EvoGeoBundle:Country")->find($birthCountry); 

      $this->removeConditionalFields($form); 

      if ($country instanceof Country && true === $country->getIsDefault()) { 
       $this->addBirthCountyField($form); 
      } 
     } 
    } 

    /** 
    * @param FormInterface $form 
    */ 
    private function addBirthCountyField(FormInterface $form) 
    { 
     $form 
      ->add('birthCounty', 'evo_geo_bundle_autocomplete_county_type', [ 
       'label' => 'Département de naissance', 
       'attr' => [ 
        'required' => true, 
       ], 
      ]) 
     ; 
    } 

    /** 
    * @param FormInterface $form 
    */ 
    private function removeConditionalFields(FormInterface $form) 
    { 
     $form->remove('birthCounty'); 
    } 
} 

、「birthCountry」選択リストの変更説明したように、それが要求を処理し、再びビューをレンダリングコントローラ(にAJAXリクエストをトリガする:ここ

が加入者であります)documentation about dynamic form submissionに:

$form = $this->createForm(new RegistrationStep1UserType(), $user); 

if ($request->isXmlHttpRequest()) { 
    $form->handleRequest($request); 
} elseif ("POST" == $request->getMethod()) { 
    [...] 
} 

問題は次のとおりです。

私はbirthCountry選択リストとセレク上の変更を行う場合にはtaの国が「birthCounty」フィールドを非表示になって、フォームが正しくそのフィールドなしでレンダリングしますが、それはエラーメッセージを示しています。

:私は多くの異なった解決策を試してみました

Ce formulaire ne doit pas contenir des champs supplémentaires. 

または

this form should not contain extra fields (in english) 

  • RegistrationStep1UserTypeとRegistrationStep1DeclarationTypeに 'validation_groups'オプションを追加します。
  • AddSubmitイベントをAddBirに追加します。 birthCountyフィールドに'mapped' => false,を追加しても、preSetDataメソッドとpostSubmitメソッドのロジックを複製するthCountyFieldSubscriber
  • がエラーをトリガします。非常に驚くべき

私はちょうど\ symfonyの\ symfonyの\ SRC \ symfonyの\コンポーネント\フォーム\拡張\ Validatorは\ FormValidator \制約は、私が見ることができる$form->handleRequest($request);

後しかし、ベンダーにそれをダンプした場合であっても$form->getExtraData()空であります余分なフィールドここ

array(1) { 
    ["birthCounty"]=> 
    string(0) "" 
} 

// Mark the form with an error if it contains extra fields 
    if (count($form->getExtraData()) > 0) { 
     echo '<pre>'; 
     \Doctrine\Common\Util\Debug::dump($form->getExtraData()); 
     echo '</pre>'; 
     die(); 

     $this->context->addViolation(
      $config->getOption('extra_fields_message'), 
      array('{{ extra_fields }}' => implode('", "', array_keys($form->getExtraData()))), 
      $form->getExtraData() 
     ); 
    } 

は私がについて何かを欠場動的な追加フィールドを作成しますか?

答えて

0

私はすべての質問を分析しませんでしたが、ロジックを反転することができます:条件を満たしていない場合は常にそのフィールドを追加して削除してください。

あなたはpostSubmitで操作を実行する必要はありません。その方法(問題がどこにあることがある)

+0

これはおそらく動作しますが、それは本当に回避策のように見えます。 – VaN

+0

@VaN本当に回避策がわからない – DonCallisto

関連する問題