Зависимые поля внутри collectionType - PullRequest
0 голосов
/ 08 апреля 2020

Что у меня есть ...

Получил операционную форму, содержащую коллекцию PaymentEmbeddedForm.

Что я намерен сделать

Я хочу добавить несколько зависимых полей в свой записи внутри коллекции PaymentEmbeddedForm.

Стена, которую я бью.

Если некоторые поля динамически добавляются в одну из моих PaymentEmbeddedForm, тогда когда передается OperationForm (форма root) , он не распознает новые данные, только поле, из которого связаны другие зависимые поля.

Пример

  • OperationFrom
    • field1
    • field2
    • field3: (Коллекция PaymentEmbeddedForm)
    • Payment1 (PaymentEmbeddedForm)
      • Payment1.field1
      • Payment1.field2
      • Payment1.field3 (динамически добавляется)
    • Payment2 (PaymentEmbeddedForm)
      • Payment2.field1
      • Payment2.field2

В этом случае e, данные Payment1.field3 не будут связаны в моей форме ....

То, что я пробовал

Манипулирование событиями внутри PaymentEmbeddedForm

Если я создаю Независимый PaymentEmbeddedForm, проблем нет, поля зависимостей в моей форме хорошо связаны.

Манипулирование событиями внутри OperationForm

Когда я отлаживаю данные формы с помощью dump ($ data ) , я не вижу данных полей зависимых. Они всегда равны нулю при первой передаче. Но как только форма была отправлена ​​хотя бы один раз, следующая субмиссия в порядке, данные хорошо связаны.

Мой код


//****************************************
//PaymentEmbeddedForm.php
//****************************************

class PaymentEmbeddedForm extends AbstractType
{
    /** @var AccountRepository  $accountRepo*/
    private $accountRepo;

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        /** @var Organization $org */
        $org = $options['organization'];

        $builder
            ->add('method', EntityType::class, [
                'placeholder' => '-- Choississez un moyen de paiement --',
                'class' => PaymentMethod::class,
                'choice_label' => 'displayName',
                'choice_value' => 'name'
            ])
        ;

        $builder
            ->addEventListener(FormEvents::PRE_SET_DATA, function(FormEvent $event) use ($org) {
                return $this->onPreSetData($event, $org);
            })
            ->get('method')->addEventListener(FormEvents::POST_SUBMIT, function(FormEvent $event) use ($org) {
                return $this->methodOnPostSubmit($event, $org);
            })
        ;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        parent::configureOptions($resolver);

        $resolver->setDefaults([
            'data_class' => Payment::class,
            'organization' => false
        ]);

        $resolver->setAllowedTypes('organization', 'App\Entity\Core\Organization');

    }

    public function onPreSetData(FormEvent $event, Organization $org)
    {
        /** @var Payment $payment */
        $payment = $event->getData();

        if (!$payment)
            return;

        $this->setupSpecificMethodFields($event->getForm(), $payment->getMethod(), $org);
        return;

    }
    public function methodOnPostSubmit(FormEvent $event, ?Organization $org)
    {
        $form = $event->getForm();

        $this->setupSpecificMethodFields(
            $form->getParent(),
            $form->getData(),
            $org
        );
    }

    private function setupSpecificMethodFields(FormInterface $form, ?PaymentMethod $method, ?Organization $org)
    {

//        $form
//            ->remove('account')
//            ->remove('amount')
//            ->remove('iban')
//            ->remove('number')
//            ->remove('paidAt')
//            ->remove('isPaid')
//        ;

        if (null === $method) {
            return;
        }

        $this->setupAmountField($form);
        $this->setupPaidAtField($form);
        $this->setupIsPaidField($form);

        if (in_array($method->getName(), ['cash', 'credit_card', 'check', 'transfer', 'direct_debit', 'direct_debit_in_installments', 'interbank_payment_order']))
            $this->setupAccountField($form, $method, $org);
        if (in_array($method->getName(), ['check', 'voucher']))
            $this->setupNumberField($form);
        if (in_array($method->getName(), ['direct_debit', 'direct_debit_in_installments']))
            $this->setupIbanField($form);

    }

    private function setupPaidAtField(FormInterface $form): void
    {
        $form->add('paidAt', DateType::class);
        return;
    }
    private function setupIsPaidField(FormInterface $form): void
    {
        $form->add('isPaid');
        return;
    }
    private function setupAccountField(FormInterface $form, PaymentMethod $method, Organization $org): void
    {

        $accountChoices = new ArrayCollection();

        switch($method->getName()) {
            case 'cash':
                $accountChoices = $org->getBankAccounts();
                break;
            case 'credit_card':
            case 'check':
            case 'transfer':
            case 'direct_debit':
            case 'direct_debit_in_installments':
            case 'interbank_payment_order':
                $accountChoices = $org->getBankAccounts();
                break;
        }

        $form->add('account', AccountType::class, [
            'choices' => $accountChoices
        ]);
    }
    private function setupAmountField(FormInterface $form): void
    {
        $form->add('amount', MoneyType::class);
        return;
    }
    private function setupIbanField(FormInterface $form): void
    {
        $form->add('iban');
    }
    private function setupNumberField(FormInterface $form): void
    {
        $form->add('number');
    }
}



//****************************************
// OperationFormType.php
//****************************************


class OperationFormType extends AbstractType
{
    /** @var AccountRepository  $accountRepo*/
    private $accountRepo;

    public function __construct(EntityManagerInterface $em)
    {
        $this->accountRepo = $em->getRepository(Account::class);
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('name')
            ->add('amount', MoneyType::class)
            ->add('description', TextareaType::class)
            ->add('account', AccountType::class, [
                'choices' => $this->accountRepo->getChildren($this->accountRepo->findOneBy([
                    'code' => $options['type'] == 'income' ? 7 : 6,
                    'chart' => $options['organization']->getChart()->getId()
                ]), false, null, 'ASC', false)
            ])
            ->add('operateAt', DateType::class)
            ->add('payments', CollectionType::class, [
                'entry_options' => [
                    'organization' => $options['organization']
                ],
                'entry_type' => PaymentEmbeddedForm::class,
                'allow_delete' => true,
                'allow_add' => true,
                'prototype' => true
            ])

            ->add('reset', ResetType::class, [
                'label' => 'Réinitialiser'
            ])
            ->add('submit', SubmitType::class, [
                'label' => 'Enregistrer'
            ])
        ;

        $builder->addEventListener(FormEvents::PRE_SET_DATA, array($this, 'onPreSetData'));

        parent::buildForm($builder, $options);
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        parent::configureOptions($resolver);

        $resolver->setDefaults([
            'data_class' => OperationFormModel::class,
            'organization' => false,
            'type' => null
        ]);

        $resolver
            ->setAllowedTypes('organization', 'App\Entity\Core\Organization')
            ->setAllowedTypes('type', ['string', 'null'])
            ->setAllowedValues('type', ['expense', 'income', null])
        ;
    }

    public function onPreSetData(FormEvent $event)
    {
        /** @var OperationFormModel $data */
        $data = $event->getData();

        if ($data->getPayments()->isEmpty()) {
            $newPayment = new Payment();
            $newPayment->setPaidAt(new DateTime());
            $data->addPayment($newPayment);
        }
    }
}

Спасибо за вашу помощь.

Бдисклаз

...