#javascript #php #html #forms #symfony
#javascript #php #HTML #формы #symfony
Вопрос:
Я пытаюсь создать форму, которая сопоставляется с объектом типа «Участник». Участник находится в отношениях «один к одному» с «человеком». Добавляя участника, я хочу сначала предоставить возможность выбрать человека, который уже есть в базе данных, и, если нужного человека не существует, создайте этого человека с помощью формы участника.
Это работает, если я делаю это с двумя страницами / формами. Первый пытается выбрать существующего пользователя, в противном случае откройте новую страницу с другой формой. Первая страница:
$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, если они выбраны. В противном случае, если пользователь не выбран, а форма отправлена с введенными данными, необходимо создать нового пользователя и сохранить его в базе данных.
К сожалению, невозможно отобразить ‘person’ дважды, один раз в виде выпадающего списка и один раз в виде формы PersonType. Итак, как мне добиться того, чего я хочу, без нереального количества JavaScript?
Моим текущим решением было бы вручную создать все необходимые поля с помощью JavaScript и заполнить их данными person, которые я получу с помощью другого запроса Ajax в событии onchange в раскрывающемся списке person, затем в событии PRE_SUBMIT формы удалите поле ‘person’ и добавьте его снова в качестве поля PersonTypeпроверьте, соответствуют ли введенные данные существующему или новому пользователю, а затем действуйте соответствующим образом. Должно быть лучшее решение, верно?
События формы, к сожалению, в остальном оказались в основном бессмысленными, поскольку невозможно подключить прослушиватель событий к событию «изменить» в одном из полей.
Спасибо.
Ответ №1:
В итоге я решил это с помощью поля выбора пользователя без сопоставления и javascript для автоматического обновления данных (с использованием ajax).
участник / add.twig:
{% 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 %}
Добавить ParticipantController:
$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() amp;amp; $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);
}
PersonController Ajax:
/**
* @Route("/{id}/data", name="person_data_ajax", methods={"GET"}, options={"expose": true})
*/
public function dataAjax(Person $person, PhoneNumberHelper $phonenumberHelper)
{
$arr = [
'id' => $person->id,
'gender' => $person->getGender(),
'title' => $person->getTitle(),
'firstName' => $person->getFirstName(),
'lastName' => $person->getLastName(),
'email' => $person->getEMail(),
'telephone' => $person->getTelephone() ? $phonenumberHelper->format($person->getTelephone(), PhoneNumberFormat::NATIONAL) : null,
'company' => $person->getCompany() ? [
'id' => $person->getCompany()->id,
'text' => $person->getCompany()->__toString()
] : null
];
return new JsonResponse($arr);
}
Надеюсь, это может помочь кому-то еще. Действительно разочарован тем, насколько ограничены формы Symfony.