Symfony 5.1 - 提交前动态添加 CustomType 字段
Symfony 5.1 - Dynamically add a CustomType field before submitting
我的问题没那么简单我会尽量总结一下。
假设我有一个实体 Vehicle,它与实体 Engine 相关。 Engine 实体是由 2 类 实现的抽象类型:ElectricEngine 和 GasEngine .
我想为 Vehicle 创建一个表单,它将创建一个车辆及其引擎类型,但我无法添加绑定了 Engine 实体的 CustomType 字段,因为它是一个抽象实体.所以我需要使用 ElectricEngine 或 GasEngine 动态添加 CustomType 字段。这是 VehicleType.php :
// App\Form\VechicleType::buildForm
$builder
->add('wheels', IntegerType::class)
->add('type', ChoiceType::class, [
'choices' => [
'ElectricEngine' => 1,
'GasEngine' => 2
],
'mapped' => false
])
所以当用户提交此表单时,我想取消提交并添加我的 ElectricEngineType 或我的 GasEngineType 字段,具体取决于哪一个我的用户选择了。
目前,这是我的解决方案:我在构建 VehicleForm 时使用 POST_SUBMIT 事件。我正在观察用户选择的类型,并添加匹配的字段。然后我添加一个错误以取消提交,以便再次呈现表单,但使用新字段。
// App\Form\VehicleTypeForm::buildForm
// After building form ...
$builder->get('type')->addEventListener(FormEvents::POST_SUBMIT, function(FormEvent $event){
$form = $event->getForm()->getParent();
if($form->get('type')->getData() != null) {
switch ($form->get('type')->getData()) {
case 1:
$form->add('engine', ElectrineEngine::class);
$form->remove('type');
break;
case 2:
$form->add('engine', GasEngine::class);
$form->remove('type');
break;
default:
// Do Nothing
}
// Adding Error so the form is not submitted
$form->addError(new FormError('Adding engine field'));
}
});
通过添加错误,表单不再有效,因此将再次呈现。
如果有人和我有同样的问题,这是一个解决方案。
但我认为它不是最好的,因为我在表格中添加了一个错误,并且没有错误。我想有一个更好的方法来实现这个,但我不知道该怎么做。
我考虑过使用 https://github.com/craue/CraueFormFlowBundle 来使用多个步骤,但这会添加电动引擎和燃气引擎步骤,我们将不得不跳过一个。我认为这不是最好的主意,因为在我的真实项目中(当然我没有开发任何车辆和引擎)我有抽象实体的 3 个子代,而且还会有更多。也许这个捆绑包是最好的主意,但我不太确定:/
我找到了更好的解决方案。对于遇到同样问题的人,这是给你的。
最好的方法是拥有多种形式,每次都添加通用部分,而不是做一种通用形式并对其进行调整。是我笨,没想到
以车辆为例:我们将有一个带有通用字段的 VehicleForm。这里是 ElectricEngineForm :
// App\Form\ElectricEngineForm
public function buildForm(FormBuilderInterface $builder, array $options)
{
$genericType = new VehicleType();
$genericType->buildForm($builder, $options);
$builder->add('engine', ElectricEngineType::class);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Vehicle::class
]);
}
ElectricEngineType 是包含 ElectricEngine 特性的形式。您还必须创建 GasEngineForm 和 GasEngineType。然后根据用户选择的路线渲染你想要的那个。
如果用户在 /vehicle/add/electric,那么我们渲染 ElectricEngineForm,否则如果他在 /vehicle/add/gas,那么我们渲染 GasEngineForm。
如果您愿意,可以使用我认为的其他方法构建通用表单。也许是静态方法,否则我不知道。
我的问题没那么简单我会尽量总结一下。
假设我有一个实体 Vehicle,它与实体 Engine 相关。 Engine 实体是由 2 类 实现的抽象类型:ElectricEngine 和 GasEngine .
我想为 Vehicle 创建一个表单,它将创建一个车辆及其引擎类型,但我无法添加绑定了 Engine 实体的 CustomType 字段,因为它是一个抽象实体.所以我需要使用 ElectricEngine 或 GasEngine 动态添加 CustomType 字段。这是 VehicleType.php :
// App\Form\VechicleType::buildForm
$builder
->add('wheels', IntegerType::class)
->add('type', ChoiceType::class, [
'choices' => [
'ElectricEngine' => 1,
'GasEngine' => 2
],
'mapped' => false
])
所以当用户提交此表单时,我想取消提交并添加我的 ElectricEngineType 或我的 GasEngineType 字段,具体取决于哪一个我的用户选择了。
目前,这是我的解决方案:我在构建 VehicleForm 时使用 POST_SUBMIT 事件。我正在观察用户选择的类型,并添加匹配的字段。然后我添加一个错误以取消提交,以便再次呈现表单,但使用新字段。
// App\Form\VehicleTypeForm::buildForm
// After building form ...
$builder->get('type')->addEventListener(FormEvents::POST_SUBMIT, function(FormEvent $event){
$form = $event->getForm()->getParent();
if($form->get('type')->getData() != null) {
switch ($form->get('type')->getData()) {
case 1:
$form->add('engine', ElectrineEngine::class);
$form->remove('type');
break;
case 2:
$form->add('engine', GasEngine::class);
$form->remove('type');
break;
default:
// Do Nothing
}
// Adding Error so the form is not submitted
$form->addError(new FormError('Adding engine field'));
}
});
通过添加错误,表单不再有效,因此将再次呈现。 如果有人和我有同样的问题,这是一个解决方案。
但我认为它不是最好的,因为我在表格中添加了一个错误,并且没有错误。我想有一个更好的方法来实现这个,但我不知道该怎么做。
我考虑过使用 https://github.com/craue/CraueFormFlowBundle 来使用多个步骤,但这会添加电动引擎和燃气引擎步骤,我们将不得不跳过一个。我认为这不是最好的主意,因为在我的真实项目中(当然我没有开发任何车辆和引擎)我有抽象实体的 3 个子代,而且还会有更多。也许这个捆绑包是最好的主意,但我不太确定:/
我找到了更好的解决方案。对于遇到同样问题的人,这是给你的。
最好的方法是拥有多种形式,每次都添加通用部分,而不是做一种通用形式并对其进行调整。是我笨,没想到
以车辆为例:我们将有一个带有通用字段的 VehicleForm。这里是 ElectricEngineForm :
// App\Form\ElectricEngineForm
public function buildForm(FormBuilderInterface $builder, array $options)
{
$genericType = new VehicleType();
$genericType->buildForm($builder, $options);
$builder->add('engine', ElectricEngineType::class);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Vehicle::class
]);
}
ElectricEngineType 是包含 ElectricEngine 特性的形式。您还必须创建 GasEngineForm 和 GasEngineType。然后根据用户选择的路线渲染你想要的那个。
如果用户在 /vehicle/add/electric,那么我们渲染 ElectricEngineForm,否则如果他在 /vehicle/add/gas,那么我们渲染 GasEngineForm。
如果您愿意,可以使用我认为的其他方法构建通用表单。也许是静态方法,否则我不知道。