dongliu5475 2015-11-04 21:47
浏览 90

使用EventSubscriber动态添加选项到Symfony2表单

I am trying to set the choices for a form select dynamically since the choices come from a service call. However, when the form renders in the view, the choices are not there.

I'm doing the following in the FormType

<?php

namespace My\Form\Customer;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;

class ItemReturnRequestForm extends AbstractType
{

    /**
     * @var EventSubscriberInterface
     */
    protected $reasonsSubscriber;

    /**
     * Returns the name of this type.
     *
     * @return string The name of this type
     */
    public function getName()
    {
        return 'item_return_request';
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('reason', 'choice', [
            'label' => 'order.returns.reason_for_return',
            'required' => true,
            'multiple' => false,
            'expanded' => false,
            'placeholder' => 'order.returns.reasons.empty',
            'empty_data' => null,
        ]);

        $builder->addEventSubscriber($this->reasonsSubscriber);
    }

    /**
     * @param EventSubscriberInterface $reasonsSubscriber
     */
    public function setReasonsSubscriber(EventSubscriberInterface $reasonsSubscriber)
    {
        $this->reasonsSubscriber = $reasonsSubscriber;
    }
}

The FormType has a service definition which injects the EventSubscriber instance since that is also a service definition with it's own dependencies.

The EventSubscrbier looks like

<?php

namespace My\Form\EventSubscriber;

use My\Customer\ItemReturnAware;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;

class ReturnReasonEventSubscriber implements EventSubscriberInterface
{
    use ItemReturnAware;

    public static function getSubscribedEvents()
    {
        return [
            FormEvents::PRE_SET_DATA => 'getReturnReasons',
        ];
    }

    public function getReturnReasons(FormEvent $event)
    {
        $form = $event->getForm();

        if ($form->has('reason')) {
            $options = $form->get('reason')->getConfig()->getOptions();
            $options['choices'] = $this->itemReturnService->getReasons();

            $form->add('reason', 'choice', $options);
        }
    }
}

Everything seems to work fine up until this point. Using XDEBUG I can see that the EventSubscriber is being triggered. The service call sets $option['choices'] to the expected array value & the field is added successfully.

However, when the form gets rendered. it's as if the EventSubscriber had never been called.

If it makes a difference, the options array is an un-ordered numeric list.

i.e.

$options = [
    10 => 'First choice',
    15 => 'Second choice',
    20 => 'Third choice',
];

Any ideas?

  • 写回答

0条回答 默认 最新

    报告相同问题?

    悬赏问题

    • ¥15 python按要求编写程序
    • ¥15 Python输入字符串转化为列表排序具体见图,严格按照输入
    • ¥20 XP系统在重新启动后进不去桌面,一直黑屏。
    • ¥15 opencv图像处理,需要四个处理结果图
    • ¥15 无线移动边缘计算系统中的系统模型
    • ¥15 深度学习中的画图问题
    • ¥15 java报错:使用mybatis plus查询一个只返回一条数据的sql,却报错返回了1000多条
    • ¥15 Python报错怎么解决
    • ¥15 simulink如何调用DLL文件
    • ¥15 关于用pyqt6的项目开发该怎么把前段后端和业务层分离