我希望能够动态添加实体,而不必在EntityType表单类型的选项选项中预设它们。我需要修改可用的选项,否则会弹出invalid value
错误。
class MyImageType extends AbstractType {
public function __construct($em) {
$this->em = $em;
}
public function configureOptions(OptionsResolver $resolver) {
$resolver->setDefaults(array(
'class' => 'stuff/MyImage',
'choice_label' => 'id',
'multiple' => true,
'choices' => [],
));
}
public function buildForm(FormBuilderInterface $builder, array $options) {
//
}
public function getParent() {
return EntityType::class;
}
}
我正在使用它:
$builder->add('images', 'stuff\MyImage\Form\Type\MyImageType')
生成的html如下所示:
<select id="product_images" name="product[images][]" required="required" class="form-control" multiple="multiple">
</select>
我正在执行一些ajax调用来创建实体,并将id附加到下拉列表中,如下所示:
<select id="product_images" name="product[images][]" required="required" class="form-control" multiple="multiple">
<option value="88" selected="selected">88</option>
</select>
88
是现有实体的现有ID。
如果我在此之后提交表单,则会显示invalid value
错误,因为88
不在此实体类型的预设choices
中。所以我需要在可用的选项中添加88
。
如果这是表单的子项(Symfony \ Component \ Form \ Form),我可以在FormEvents::PRE_SUBMIT
上执行此操作
//..
$img = $em->findOneById(88);
$form->add('images', [
'class' => 'stuff/MyImage',
'choice_label' => 'id',
'multiple' => true,
'choices' => [$img],
]);
但在我的情况下,我想在MyImageType
类中进行封装。你能告诉我怎么做的指示吗?感谢。
修改
在撰写此问题的过程中,我找到了解决方法。如果我可以像这样更新字段:
$builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) use($em) {
$form = $$event->getForm();
$form->getParent()->add('images', EntityType::class, $options);
}
我仍然不想回答我自己的问题,因为也许有更好的方法来做。感谢。
答案 0 :(得分:0)
查看我的FormBundle。
为了解决这个问题,我在PRE_SUBMIT FormEvent中挂钩,然后我重新创建了一个将提交的选项注入到新选项中的孩子&#39;选项。
如果您希望在编辑实体时填充您的字段,则必须在PRE_SET_DATA中执行相同操作。
<强>注意强>
这样做,每个现有的提交实体都是有效值。 如果只有部分实体可供选择,您还应该在字段中添加约束。
答案 1 :(得分:0)
我知道这是一个老问题,我已经看过您的上一次编辑,但是我认为您的解决方案应该更像这样(以保留“嵌入的”表单名称及其类,因为它不是EntityType而是自定义类型。
我以自定义表单类型添加了这段代码:
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) use ($options): void {
$data = $event->getData();
if ($data === null || $data === []) {
return;
}
// The following works with both "multiple" true and false.
$entityIds = is_array($data) ? $data : [$data];
$entities = $this->yourInjectedRepository->findByIds($entityIds);
// Self-replace this form in its parent with a clone (same name and options) that has the needed choices.
$options['choices'] = $entities;
$event->getForm()->getParent()->add(
$event->getForm()->getName(),
self::class,
$options
);
});
}