我有一个用例,我需要在 Symfony 5 中构建的动态表单上使用一些默认条件逻辑。
让我试着用一个简单的表格来解释我的用例是什么以及我的问题。例如,我有一个包含两个字段的表单产品:
- 部分(选择类型 => 左、右)
- 长度(数字类型)
更改时,所有字段 (:input) 都通过 Ajax 请求提交。我有两种控制器方法,一种用于访问页面(正在构建表单),另一种用于通过 ajax 请求呈现表单(处理条件逻辑)。
对于条件逻辑部分,需要完成以下操作
- 剩下部分时,默认长度需要为 50
- 当部分正确时,默认长度需要为 100
- 用户可以更改默认数据
根据左或右设置长度的默认数据不是问题。选择 left 时,默认长度变为 50。当将值更改为 55(每次更改都提交表单)时,它再次变为 50。这种行为是合乎逻辑的,但是如何覆盖默认数据呢?
上述情况也可以描述为给用户默认数据并选择更改它
表格类型
<?php
// ... namespace, use statments
class ProductType extends AbstractType
{
/**
* {@inheritDoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder->add('part', ChoiceType::class, array(
'choices' => array(
'Left' => 'left',
'Right' => 'right',
)
));
$builder->add('length', NumberType::class);
$builder->addEventListener(FormEvents::POST_SET_DATA, function(FormEvent $event) use ($options)
{
$form = $event->getForm();
if(null === $product = $event->getData()) {
return;
}
switch($product->getPart()) {
case 'left': $defaultLength = 50; break;
case 'right': $defaultLength = 100; break;
default: $defaultLength = 0;
}
$form->get('length')->setData($defaultLength);
});
}
/**
* {@inheritDoc}
*/
public function getName(): string
{
return 'product';
}
/**
* {@inheritDoc}
*/
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults(array(
'data_class' => Product::class,
'translation_domain' => 'forms',
));
}
}
控制器
// src/Controller/ProductController.php
// ... namespace, use statments
namespace App\Controller;
class ProductController extends AbstractController
{
public function productAction(Request $request): Response
{
$product = new Product();
$form = $this->createForm(ProductType::class, $product);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$product = $form->getData();
dd($product);
}
return $this->render('product_view.html.twig', array(
'form' => $form->createView()
));
}
public function productConfigureAjaxAction(Request $request): Response
{
$product = new Product();
$part = $request->request->get('product')['part'] ?? null;
$product->setPart($part);
$form = $this->createForm(ProductType::class, $product);
$form->handleRequest($request);
// product_form.html.twig is an separated file and included in product_view.html.twig
// by making the form separated is could been used for an ajax response
return $this->render('product_form.html.twig', array(
'form' => $form->createView()
));
}
}