我有一个表单类型
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();
}
// ...
}
如何让选择动态化?
我找到了解决方案。在 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);
}