Symfony 表单:如何根据实体的其他属性设置动态选择?

问题描述 投票:0回答:1

我有一个表单类型

class ArticleTranslationType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('locale', ChoiceType::class, [
                'choices' => $this->getLocales($builder), // need to implement
            ];
    }

    // ...
}

我需要实现方法

getLocales
。它是依赖于其他翻译的动态列表。如果其他同级的翻译已存在,则它不应在此列表中 在控制器中我这样构建它


class ArticleController extends AbstractController
{
    public function update(Request $request): Response
    {
        // ...
        //getting article and translation from EM

        $form = $this->createFormBuilder([
            'article' => $article,
            'translation' => $translation,
        ])
        ->add('article', ArticleType::class)
        ->add('translation', ArticleTranslationType::class)
        ->getForm();
    }
    // ...
}

如何让选择动态化?

php symfony symfony-forms
1个回答
0
投票

我找到了解决方案。在 buildForm 方法的底部我添加了

class ArticleTranslationType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        //...
        $builder->addEventListener(FormEvents::PRE_SET_DATA, $this->buildLocale(...));
    }

    private function buildLocale(FormEvent $event): void
    {
        $event->getForm()
            ->add('locale', ChoiceType::class, [
                'choices' => $this->getAvailableLocales($event->getData()),
                'label' => $this->translator->trans('Locale', [], 'article'),
                'attr' => [
                    'class' => 'form-select',
                ],
                'constraints' => [
                    new UniqueTranslation()
                ],
            ]);
    }

    /**
     * @param ArticleTranslation $articleTranslation
     * @return array<string, string>
     */
    public function getAvailableLocales(ArticleTranslation $articleTranslation): array
    {
        $availableLocales = array_flip($this->language->buildLanguages());
        $translations = $articleTranslation->getArticle()->getArticleTranslations();
        foreach ($translations as $translation) {
            if ($translation->getId() != $articleTranslation->getId() && isset($availableLocales[$translation->getLocale()])) {
                unset($availableLocales[$translation->getLocale()]);
            }
        }

        return array_flip($availableLocales);
    }
© www.soinside.com 2019 - 2024. All rights reserved.