我有一个嵌入的表单,其中的实体字段Activity是子表单,动态填充了来自字段模块的数据,该字段的数据是通过ajax请求设置的。
但是当我提交表单时,我遇到验证错误(“此值无效”),并且活动字段为空白。
原理:
主表单(会话)具有一个实体字段module
,并包含一个集合(时隙)。
“时间段”子表单具有字段activity
,其内容取决于模块值。
我的表格:
class SessionType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('module', EntityType::class, [
'label' => 'module.name',
'required' => true,
'class' => Module::class,
'placeholder' => 'choose',
])
->add('timeslots', CollectionType::class, [
'required' => true,
'constraints' => new Valid(),
'prototype_name' => '__timeslot_prot__',
'entry_type' => TimeslotType::class,
'entry_options' => ['module' => isset($module) ? $module->getId() : 0],
'by_reference' => false,
'allow_add' => true,
'allow_delete' => true,
]);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Session::class,
'module' => null,
]);
}
}
And the Timeslot
class TimeslotType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$module = $options['module'];
$builder
->add('activity', EntityType::class, [
'class' => Activity::class,
'multiple' => false,
'required' => true,
'constraints' => new NotBlank(),
'query_builder' => function (ActivityRepository $activity) use ($module) {
if (null !== $module) {
$qb = $activity->createQueryBuilder('a')
->join('a.activityGroups', 'ag')
->join('ag.module', 'm')
->where('m.id = :mid')
->setParameter('mid', $module)
->orderBy('a.name', 'ASC');
return $qb;
} else {
$qb = $activity->createQueryBuilder('a')
->where('a.id = 0');
return $qb;
}
},
]);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Timeslot::class,
'module' => null,
]);
}
}
我还有一个JavaScript脚本,可通过ajax调用用查询填充“活动选择”选项。
我还尝试遵循此symfony doc修改我的TimeslotType 但是我偶然发现了一个问题,就我而言,Module字段与Activity不在同一formBuilder中,因此POST_SUBMIT事件侦听器无法应用于我的情况。
class TimeslotType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$module = $options['module'];
$formModifier = function (FormInterface $form, Module $module = null) {
$activities = [];
if (null !== $module){
foreach($module->getActivityGroups() as $ag){
foreach($ag->getActivities() as $activity){
$activities[] = $activity;
}
}
}
$form->add('activity', EntityType::class, [
'label' => 'timeslot.activity',
'label_attr' => ['class' => 'mandatory', 'data-extrainfo' => 'panel_timeslot'],
'attr' => [
'class' => 'activitieslist',
],
'class' => Activity::class,
'multiple' => false,
'required' => true,
'constraints' => new NotBlank(),
'choices' => $activities,
'choices_as_values' => true,
]);
};
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
function (FormEvent $event) use ($formModifier) {
// the entity : Timeslot
$data = $event->getData();
$formModifier($event->getForm(), $module);
}
);
//$builder->get('module') ... Makes no sense here since the module attribute is not a Timeslot, but belongs to Session
/*
$builder->get('module')->addEventListener(FormEvents::PRE_SUBMIT,
function (FormEvent $event) use ($formModifier) {
$module = $event->getForm()->getData();
$formModifier($event->getForm()->getParent(), $module);
}
);
*/
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Timeslot::class,
'module' => null,
]);
}
}
如何解决我的问题并验证我的表格?
===
更改模块字段时将调用ajax请求
function updateActivities(block) {
var module = $('#session_module').val();
if (module != ''){
$.ajax({
url: Routing.generate('project_module_activities_ajax', {}),
data: { 'module': module },
method: 'POST',
success: function (activities) {
var sel = '';
for (var i = 0; i < activities.length; i++) {
sel += '<option value="' + activities[i].id + '">' + activities[i].name + '</option>'
}
$('#litimeslot'+block).find('.activitieslist').each(function () {
$(this).html(sel);
})
}
});
}
}
并且路由project_module_activities_ajax
只是从查询中返回模块的活动数组
像这样:
[
['id' : 1, 'name' : 'activity 1'],
['id' : 2, 'name' : 'activity 2'],
}
如果我将此事件监听器添加到TimeslotType中:
$builder->addEventListener(FormEvents::PRE_SUBMIT,
function (FormEvent $event) use ($moduleId) {
$form = $event->getForm();
$data = $event->getData();
echo '<pre>form AFTER=';var_dump($form->getData());echo '</pre>';
echo '<pre>data AFTER=';var_dump($data);echo '</pre>';
echo '<pre>module AFTER';var_dump($moduleId);echo '</pre>';
}
);
我有
form AFTER= NULL
data AFTER= array(
["activity"]=>
string(3) "573" <= which is the value i selected
...
)
module AFTER int(0)