动态修改表单预设选项以在symfony2中传递验证

时间:2016-07-27 14:29:05

标签: symfony symfony-forms

我希望能够动态添加实体,而不必在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);
}

我仍然不想回答我自己的问题,因为也许有更好的方法来做。感谢。

2 个答案:

答案 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
            );
        });
    }