我正在尝试创建一个映射到“参与者”类型的实体的表单。参与者与“人”一对一关系。添加一个参与者,我首先要提供选择数据库中已经存在的人的选项,如果不存在合适的人,请使用参与者表单创建该人。
如果我用两个页面/表格来完成此操作。第一个尝试选择一个现有的人,否则用不同的形式打开一个新页面。 第一页:
$form->add('person', AjaxEntityType, [ // EntityType but with select2 ajax
'class' => Person::class,
'remote_route' => 'person_ajax_list'
]);
第二页:
$participant->setPerson(new Person());
$form->add('person', PersonType::class);
// adds PersonType fields to the Participant form
那很好,但是非常缓慢而且没有必要。我更希望同时显示两个字段,如果选择了PersonType表单字段(名字,姓氏,职务,公司,地址等),则这些字段将自动填充有persons数据。否则,如果未选择任何人员,并且使用输入的数据提交表单,则应创建一个新的人员并保存在数据库中。
可悲的是,不可能两次渲染“人物”,一次是下拉菜单,一次是PersonType表单。那么,如何在没有大量JavaScript的情况下实现自己想要的目标?
我当前的解决方案是使用JavaScript手动创建所有必填字段,并在人员下拉列表中的onchange事件上使用我通过另一个Ajax请求获得的人员数据填充它们,然后在表单的PRE_SUBMIT事件中,删除“人员”字段,然后再次将其添加为“人员类型”字段,检查输入的数据是对应于现有人员还是新人员,然后采取相应措施。必须有更好的解决方案,对吧?
不幸的是,事实证明表单事件基本上是没有意义的,因为不可能将事件侦听器附加到其中一个字段上的“更改”事件。
谢谢。
答案 0 :(得分:0)
最终使用一个未映射的人员选择字段和javascript(使用ajax)自动更新数据来解决该问题。
参与者/add.twig:
{ width: 800px, height: 300px}
ParticipantController添加:
{% block javascripts %}
<script type="text/javascript">
$(document).ready(function () {
function onTrainerChange() {
let trainerId = $('#participant_person_choose').val();
$.get(Routing.generate('person_data_ajax', { id: trainerId }), function (data) {
$('#participant_person_gender').val(data.gender);
$('#participant_person_title').val(data.title);
$('#participant_person_firstName').val(data.firstName);
$('#participant_person_lastName').val(data.lastName);
$('#participant_person_email').val(data.email);
$('#participant_person_telephone').val(data.telephone);
if (data.company) {
let company = $('#participant_person_company');
company.empty();
company.append(new Option(data.company.text, data.company.id));
company.val(data.company.id);
company.trigger('change');
// manipulate dom directly because of .select('data') bug with select2 >=4.0
}
});
};
let trainer = $('#participant_person_choose');
trainer.change(onTrainerChange);
});
</script>
{% endblock %}
PersonController Ajax:
$participant = new Participant($seminar);
$person = $participant->getPerson() ?? new Person();
$participant->setPerson($person);
$form = $this->createParticipantForm($participant)
->add('person_choose', AjaxEntityType::class, [
'mapped' => false,
'class' => Person::class,
'remote_route' => 'person_select_ajax',
'placeholder' => 'form.personCreate',
'label' => 'form.person'
])
->add('person', PersonType::class);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
if ($form->get('reservation')->getData()) {
$participant->setInterested();
}
$personEntered = $form->get('person')->getData();
$personChosen = $form->get('person_choose')->getData();
if ($personChosen) {
$person = $personChosen;
$person->setGender($personEntered->getGender());
$person->setTitle($personEntered->getTitle());
$person->setFirstName($personEntered->getFirstName());
$person->setFirstName($personEntered->getLastName());
$person->setCompany($personEntered->getCompany());
$person->setEmail($personEntered->getEmail());
$person->setTelephone($personEntered->getTelephone());
$participant->setPerson($person);
}
$this->getDoctrine()->getManager()->persist($person);
$this->getDoctrine()->getManager()->persist($participant);
}
希望这可以帮助其他人。真的对Symfonys表格的数量感到失望。