【发布时间】:2019-09-03 19:49:38
【问题描述】:
我尝试编写一个动态表单来编辑用户。
里面有一个邮政编码(codePostal)。如果有人更改邮政编码,它应该更改城市列表(公社)。 我使用 Symfony 推荐的动态表格。这对我的 RegisterForm 非常有效,但不适用于这个 editForm。
我想,我错过了从用户那里获取信息的东西? 因此,每次我更改邮政编码时,它都无法获取动态表单并在我的控制台 (ajax) 中创建此异常:预期参数类型为“string”,属性路径“civilite”中给出的“NULL”。
这个异常是在 $form->handleRequest($request);我的控制器,但就在我更改邮政编码时,而不是在第一次加载表单时。
这是我的代码:
//Form/EditUserFormType.php
class EditUserFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$user = $options['data'];
$builder
->add('civilite',ChoiceType::class, array(
'choices' => array('M.' => '1', 'Mme' => '2'),
'required' => true,
'expanded' => true,
'multiple' => false,
'data' => $user->getCivilite()
))
->add('nom')
->add('prenom')
->add('societe')
->add('telephone')
->add('adresse')
->add("codePostalAutoComplete", TextType::class, [
"mapped"=>false,
'required' => false,
"label"=>"Code postal",
])
->add('codePostal', EntityType::class, [
'class' => 'App\Entity\CodePostal',
'placeholder' => ''/
])
->add('email');
$formModifier = function (FormInterface $form, CodePostal $codePostal = null) {
$communes = null === $codePostal ? [] : $codePostal->getCommunes();
$form->add('commune', EntityType::class, [
'class' => 'App\Entity\Commune',
'placeholder' => 'Choisir une commune',
'choices' => $communes,
]);
};
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
function (FormEvent $event) use ($formModifier) {
// this would be your entity, i.e. SportMeetup
$data = $event->getData();
$formModifier($event->getForm(), $data->getCodePostal());
}
);
$builder->get('codePostal')->addEventListener(
FormEvents::POST_SUBMIT,
function (FormEvent $event) use ($formModifier) {
$codePostal = $event->getForm()->getData();
$formModifier($event->getForm()->getParent(), $codePostal);
}
);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => User::class,
]);
}
}
//Controller/AccountController.php
public function edit(Request $request): Response
{
$em = $this->getDoctrine()->getManager();
$user = $this->getUser();
$form = $this->createForm(EditUserFormType::class,$user);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($user);
$em->flush();
$this->addFlash('notice', 'Vos modifications on bien été prises en compte !');
return $this->redirectToRoute('app_account_dashboard');
}
return $this->render('account/edit.html.twig', array(
'user' => $user,
'form' => $form->createView(),
));
}
//templates/account/edit.html.twig
{% extends 'base.html.twig' %}
{% block stylesheets %}
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script>
$(document).ready(function () {
var $codePostalAutoComplete = $('#edit_user_form_codePostalAutoComplete');
var $codePostal = $('#edit_user_form_codePostal');
$codePostalAutoComplete.change(function () {
$newValue = $codePostalAutoComplete.val();
$('#edit_user_form_codePostal option').filter(function () {
return($(this).text() == $newValue); // To select Blue
}).prop('selected', true);
// ... retrieve the corresponding form.
var $form = $(this).closest('form');
// Simulate form data, but only include the selected codepostal value.
console.log($form);
var data = {};
data[$codePostal.attr('name')] = $codePostal.val();
// Submit data via AJAX to the form's action path.
$.ajax({
url: $form.attr('action'),
type: $form.attr('method'),
data: data,
success: function (html) { // Replace current position field ...
$('#edit_user_form_commune').replaceWith(
// ... with the returned one from the AJAX response.
$(html).find('#edit_user_form_commune')
);
// Position field now displays the appropriate positions.
}
});
})
});
</script>
{% endblock %}
{% block title %}Modifier mon compte
{% endblock %}
{% block body %}
<h1>Modifier mon compte</h1>
{{ form_start(form) }}
{{ form_row(form.civilite) }}
{{ form_row(form.nom) }}
{{ form_row(form.prenom) }}
{{ form_row(form.societe) }}
{{ form_row(form.adresse) }}
{{ form_row(form.codePostalAutoComplete) }}
<div style="none;">{{ form_row(form.codePostal) }}</div>
{{ form_row(form.commune) }}
{{ form_row(form.telephone) }}
{{ form_row(form.email) }}
</p>
<button class="btn" type="submit">Valider</button>
{{ form_end(form) }}{% endblock %}
有什么想法吗?谢谢
【问题讨论】:
-
如果你只提交一个字段,你需要一个不同的控制器方法来检索动态值,你不能使用表单动作。见this symfonycast。
-
谢谢,我听从了您的建议以及他们在 symfonycast 上的解释并找到了方法。祝你有美好的一天味精;)