简体   繁体   English

Sonata admin PRE_SUBMIT表单事件使admin twig变量为null

[英]Sonata admin PRE_SUBMIT form event makes admin twig variable null

i am having problems with form events in an admin class. 我在管理类中遇到表单事件的问题。 I have dynamically added choices in a custom entity type.Choices are added to the database by javascript via a controller.To be able to validate those dynamic choices (added after the form is renderd), i added a PRE_SUBMIT form event to the field in the admin class.So before the form is submitted i load the new choice list from db and remove and add the field back to the form to update its options, as shown here https://gist.github.com/webdevilopers/fef9e296e77bb879d138 我已经在自定义实体类型中动态添加了选项。通过javascript通过控制器将数据库添加到数据库中。为了能够验证这些动态选择(在表单渲染后添加),我在字段中添加了一个PRE_SUBMIT表单事件。在提交表单之前,我将从db加载新的选项列表并删除并将该字段添加回表单以更新其选项,如下所示https://gist.github.com/webdevilopers/fef9e296e77bb879d138

In the twig template of the form type i use the sonata_admin.admin variable to get needed data. 在表单类型的twig模板中,我使用sonata_admin.admin变量来获取所需的数据。 The problem is when there is an error in the form (on any other field anywhere in the form) the sonata_admin.admin variable form the twig template is null. 问题是当表单中存在错误时(在表单中的任何其他字段上),sonata_admin.admin变量形式为twig模板为null。

thanks for the help 谢谢您的帮助

admin::configureFormFields() 管理:: configureFormFields()

$class = 'LibrinfoVarietiesBundle:SelectChoice';
    $repo = $this->getConfigurationPool()->getContainer()->get('doctrine.orm.entity_manager')->getRepository($class);
    $admin = $this;
    $formBuilder = $formMapper->getFormBuilder();

    $formBuilder->addEventListener(FormEvents::SUBMIT, function ($event) use ($formBuilder, $admin, $repo, $class) {
        $form = $event->getForm();
        $subject = $admin->getSubject($event->getData());
        $label = 'librinfo_varieties_admin_variety_regulatory_status_librinfo_core_customchoice';
        $choices = $repo->findBy(array(
            'label' => $label
        ));

        $choiceViews = array();
        foreach ($choices as $choice)
        {
            $choiceViews[$choice->getvalue()] = $choice;
        }
        if ($form->has('regulatory_status'))
        {
            $form->remove('regulatory_status');
        }

        $customChoice = $formBuilder->getFormFactory()->createNamed('regulatory_status', 'librinfo_customchoice', null, array(
            'choices' => $choices,
            'class' => $class,
            'auto_initialize' => false,
        ));
        $form->add($customChoice);
    }); 

form type ConfigureOptions() 表单类型ConfigureOptions()

$label = 'librinfo_varieties_admin_variety_regulatory_status_librinfo_core_customchoice';
     $choices = $this->repo->findBy(array(
                'label' => $label
            ));
     $choiceViews = array();
     foreach ($choices as $choice)
     {
         $choiceViews[$choice->getvalue()] = $choice;
     }

    $resolver->setDefaults(array(
        'choice_label' => 'value',
        'class'        => 'LibrinfoVarietiesBundle:SelectChoice',
        'placeholder'  => '', 
        'choices'      => $choiceViews,
    ));

twig block 树枝块

{% block librinfo_customchoice_widget %}
{% set subject = sonata_admin.admin.subject %}
{% spaceless %}
    {{ block('choice_widget') }}
    {% if subject.fieldset is defined %}
        <a id="{{ subject.fieldset }}_{{ subject.field }}" class="add-choice editable editable-click inline-input" href="#"><i class="fa fa-plus-circle"></i></a>
    {% else %}
        <a id="{{ block_prefixes.4 }}" class="add-choice editable editable-click inline-input" href="#"><i class="fa fa-plus-circle"></i></a>
    {% endif %}
{% endspaceless %}
{% endblock %}

This is because the Sonata FormTypeFieldExtension is not called when you directly add field to the form object trough events. 这是因为当您通过事件直接向表单对象添加字段时,不会调用Sonata FormTypeFieldExtension

But I found a workaround, you have to add the field with the FormMapper first. 但我找到了一个解决方法,你必须首先使用FormMapper添加该字段。 This will setup sonata admin options. 这将设置sonata管理员选项。

Then, on your event callback, get back the current options of the field and merge them with your own: 然后,在您的事件回调中,获取该字段的当前选项并将它们与您自己的选项合并:

protected function configureFormFields(FormMapper $formMapper)
{
    $formMapper
        ->add('date', null, [
            'widget' => 'single_text',
        ])
        ->add('method', EnumType::class, [
            'class' => PaymentMethod::class,
            'translation_domain' => 'global',
            'prefix_label_with_class' => true,
            'attr' => [
                'class' => 'payment-method',
            ],
        ])
        ->add('reference', TextType::class, [
            'required' => false,
            'attr' => [
                'class' => 'payment-reference',
            ]
        ])
        ->add('amount')
    ;

    $builder = $formMapper->getFormBuilder();
    $factory = $builder->getFormFactory();

    $referenceTypeMaker = function (FormEvent $event) use ($factory) {
        $form = $event->getForm();
        $data = $event->getData();

        $paymentMethod = $data instanceof Payment ? $data->getMethod() : $data['method'];

        if (PaymentMethod::CREDIT_NOTE === $paymentMethod) {
            $form->add($factory->createNamed('reference', CreditNoteRefType::class, null, array_merge(
                $form->get('reference')->getConfig()->getOptions(), // Put back original options here.
                [
                    'auto_initialize' => false
                ]
            )));
        }
    };

    $builder->addEventListener(FormEvents::PRE_SET_DATA, $referenceTypeMaker);
    $builder->addEventListener(FormEvents::PRE_SUBMIT, $referenceTypeMaker);
}

As you can see on my code sample, the reference field is a TextType but can be a CreditNoteRefType depending on the payment method choice. 正如您在我的代码示例中看到的那样, reference字段是TextType但可以是CreditNoteRefType具体取决于付款方式选择。

Putting back the already defined field options to the new one solve the issue. 将已定义的字段选项放回到新的字段选项可以解决问题。

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

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