Symfony2动态/从属形式 [英] Symfony2 Dynamic/Dependent Forms
问题描述
我有一个包含3个相关字段的表单:
I have a form with 3 dependent fields:
制造商-> ManufacturerProductGroup-> ManufacturerProductSeries
Manufacturer -> ManufacturerProductGroup -> ManufacturerProductSeries
所以我想根据制造商的产品组和基于产品组的产品系列来选择制造商.
So I want to select a Manufacturer, based on the Manufacturer the ProductGroup and based on the ProductGroup the Product Series.
有一个Cookbook条目,介绍如何处理这种动态形式, 它对于ManufacturerProductGroup来说很容易工作.问题是 ManufacturerProductSeries依赖于另一个动态表单/字段.
There is a CookBook Entry about how to deal with such dynamic forms an it is easily working for the ManufacturerProductGroup. The problem is that ManufacturerProductSeries depends on another dynamic form/field.
问题是,我无法在闭包中添加侦听器,因为我只有 对FormInterface的访问不再对FormBuilderInterface了.
The problem is, that I cannot add an Listener in the closure since I have only access to the FormInterface not any more to the FormBuilderInterface.
我不能像PRE_SET_DATA侦听器中那样仅使用一个侦听器来完成此操作,因为 将被提交,这样可以防止任何修改.我要么需要一种添加方式 动态侦听器,或者仅更新POST_SUBMIT侦听器中的数据 而不是替换整个字段/表单.
I cant do it with just one listener as in the PRE_SET_DATA Listener since the form would be submitted then which prevents any modification. I either need a way to add the listener dynamically or maybe update just the data in the POST_SUBMIT listener and not to replace the entire field/form.
这是代码,由于我将侦听器添加到不存在的侦听器中,因此出现错误 表单字段(manufacturerProductGroup仅在pre_set_data事件之后可用)
This is the code which gives an error since I am adding a listener to a non existing form field (manufacturerProductGroup is only available after the pre_set_data event)
/**
* @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);
}
);
}
推荐答案
我用以下代码解决了这个问题:
I solved the matter with the following code:
$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);
这篇关于Symfony2动态/从属形式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!