【问题标题】:Symfony2 Dynamic/Dependent FormsSymfony2 动态/依赖形式
【发布时间】:2013-11-11 10:37:02
【问题描述】:

我有一个包含 3 个依赖字段的表单:

制造商 -> 制造商产品组 -> 制造商产品系列

所以我想选择一个制造商,基于制造商的产品组和基于产品组的产品系列。

有一个关于如何处理这种动态表单的 CookBook 条目 它很容易为 ManufacturerProductGroup 工作。问题是 ManufacturerProductSeries 依赖于另一个动态表单/字段。

问题是,我无法在闭包中添加监听器,因为我只有 对 FormInterface 的访问不再是对 FormBuilderInterface 的访问。

我不能像在 PRE_SET_DATA 监听器中那样只使用一个监听器,因为表单 然后将提交,以防止任何修改。我要么需要一种方法来添加 侦听器动态或仅更新 POST_SUBMIT 侦听器中的数据 而不是替换整个字段/表单。

这是给出错误的代码,因为我正在将侦听器添加到不存在的 表单字段(manufacturerProductGroup 仅在 pre_set_data 事件后可用)

/**
 * @param FormBuilderInterface $builder
 * @param array                $options
 */
public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('manufacturer', 'entity', array('class' => 'ArticleBundle:manufacturer', 'empty_value' => false));

    $manufacturerProductGroupModifier = function(FormInterface $form, Manufacturer $manufacturer)
    {
        $manufacturerProductGroups = $this->em->getRepository('ArticleBundle:ManufacturerProductGroup')
            ->findAvailableByManufacturer($manufacturer);

        $form->add(
            'manufacturerProductGroup',
            'entity',
            array(
                'class' => 'ArticleBundle:ManufacturerProductGroup',
                'empty_value' => '',
                'choices' => $manufacturerProductGroups
            )
        );
    };

    $manufacturerProductSeriesModifier = function(FormInterface $form, ManufacturerProductGroup $manufacturerProductGroup)
    {
        $manufacturerProductSeries = $this->em->getRepository('ArticleBundle:ManufacturerProductSeries')
            ->findAvailableByManufacturerProductGroup($manufacturerProductGroup);

        $form->add(
            'manufacturerProductSeries',
            'entity',
            array(
                'class' => 'ArticleBundle:ManufacturerProductSeries',
                'empty_value' => '',
                'choices' => $manufacturerProductSeries
            )
        );

    };

    $builder->addEventListener(
        FormEvents::PRE_SET_DATA,
        function(FormEvent $event) use ($manufacturerProductGroupModifier, $manufacturerProductSeriesModifier) {
            /** @var $article Article */
            $article = $event->getData();
            $manufacturerProductGroupModifier($event->getForm(), $article->getManufacturer());
            $manufacturerProductSeriesModifier($event->getForm(), $article->getManufacturerProductGroup());
        }
    );

    $builder->get('manufacturer')->addEventListener(
        FormEvents::POST_SUBMIT,
        function(FormEvent $event) use ($manufacturerProductGroupModifier) {
            $manufacturer = $event->getForm()->getData();
            $manufacturerProductGroupModifier($event->getForm()->getParent(), $manufacturer);
        }
    );

    $builder->get('manufacturerProductGroup')->addEventListener(
        FormEvents::POST_SUBMIT,
        function(FormEvent $event) use ($manufacturerProductSeriesModifier) {
            $manufacturerProductGroup = $event->getForm()->getData();
            $manufacturerProductSeriesModifier($event->getForm()->getParent(), $manufacturerProductGroup);
        }
    );
}

【问题讨论】:

标签: forms symfony


【解决方案1】:

我用下面的代码解决了这个问题:

    $addManufacturerProductSeries = function (FormEvent $event) {
        $form = $event->getForm()->getParent();
        $manufacturerProductGroup = $event->getData();

        $form->add(
            'manufacturerProductSeries',
            'entity',
            array(
                'auto_initialize' => false,
                'class' => 'ArticleBundle:ManufacturerProductSeries',
                'query_builder' => function (ManufacturerProductSeriesRepository $repository) use ($manufacturerProductGroup) {
                    return $repository->findAvailableByManufacturerProductGroupQueryBuilder($manufacturerProductGroup);
                },
            )
        );
    };

    $addManufacturerProductGroup = function (FormEvent $event) use ($factory, $addManufacturerProductSeries) {
        $form = $event->getForm()->getParent();
        $manufacturer = $event->getData();

        $fieldBuilder = $factory->createNamedBuilder(
            'manufacturerProductGroup',
            'entity',
            null,
            array(
                'auto_initialize' => false,
                'class' => 'ArticleBundle:ManufacturerProductGroup',
              'query_builder' => function (ManufacturerProductGroupRepository $repository) use ($manufacturer) {
                    return $repository->findAvailableByManufacturerQueryBuilder($manufacturer);
                },
            )
        );

        $fieldBuilder->addEventListener(FormEvents::POST_SET_DATA, $addManufacturerProductSeries);
        $fieldBuilder->addEventListener(FormEvents::POST_SUBMIT, $addManufacturerProductSeries);

        $form->add($fieldBuilder->getForm());
    };

    $builder->get('manufacturer')->addEventListener(FormEvents::POST_SET_DATA, $addManufacturerProductGroup);
    $builder->get('manufacturer')->addEventListener(FormEvents::POST_SUBMIT, $addManufacturerProductGroup);

【讨论】:

  • 这会返回错误option auto_initialize 不存在。这个选项有什么作用?以及如何实现它?
  • 这个选项可能已被弃用。您应该尝试删除它。
猜你喜欢
  • 1970-01-01
  • 2012-04-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-11
相关资源
最近更新 更多