与字段无关的 Symfony 动态表单收集错误
Symfony Dynamic Form Collection Errors Not Associated to Fields
我对 Symfony 表单集合字段有疑问。我有一个父表单,其中有两个字段是表单集合。一切都工作得很好,除非我提交带有无效数据的表单。表单集合字段的错误输出在页面的表单下方。我一直在阅读有关这些字段的 error_bubbling 的文档,并意识到对于 CollectionType 字段,它默认为 true。因此,我在每个字段上将其设置为 false,但错误仍未映射到表单上的字段。
集合字段可以通过前端javascript动态添加到页面中。我注意到,在我的标记中,在我提交表单之前,有两个错误的 <div class=""form-group">
添加到我的标记的基础上,我没有在我的模板中输出。当提交表单但无效时,将在这些 div 中输出错误。
代码;
ItemFormType;
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('shop', ShopType::class, [
'data_class' => Shop::class,
'label' => false,
])
->add('purchase', PurchaseType::class, [
'data_class' => Purchase::class,
'label' => false,
])
->add('missing_items', CollectionType::class, [
'entry_type' => MissingItemFormType::class,
'allow_add' => true,
'allow_delete' => true,
'label' => false,
'prototype' => true,
'error_bubbling' => false,
])
->add('replaced_items', CollectionType::class, [
'entry_type' => ReplacedItemFormType::class,
'allow_add' => true,
'allow_delete' => true,
'label' => false,
'prototype' => true,
'error_bubbling' => false,
])
->add('submit', SubmitType::class)
->getForm();
}
/**
* Get the form name.
*
* @return string
*/
public function getName(): string
{
return 'missing_form';
}
/**
* Set form options.
*
* @param OptionsResolver $resolver
*
* @return void
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => null,
'error_bubbling' => false
]);
}
控制器;
/**
* @Route("/", name="homepage")
*
* @param ClaimMailer $mailer
* @param Request $request
*
* @return Response
*/
public function indexAction(ClaimMailer $mailer, Request $request): Response
{
$purchase = [
'shop' => new Shop(),
'purchase' => new Purchase(),
];
$form = $this->createForm(MissingFormType::class, $purchase);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$this->store($form, $purchase);
// Send confirmation email.
$mailer->send(
$purchase['purchase']->getEmail(),
$purchase['shop']->getName(),
$purchase['purchase']->getClaimReferenceNumber()
);
return $this->render('form/form_complete.html.twig', [
'purchase_id' => $purchase['purchase']->getPurchaseReferenceNumber(),
]);
}
return $this->render('form/purchase_form.html.twig', [
'form' => $form->createView(),
]);
}
/**
* Store form data.
*
* @param Form $form
* @param array$claim
*
* @return void
*/
public function store(Form $form, $purchase){}
模板;
{% block _missing_form_missing_items_entry_row %}
{% for field in form %}
<td>
{{ form_row(field) }}
</td>
{% endfor %}
{% endblock %}
{% block _missing_form_replaced_items_entry_row %}
{% for field in form %}
<td>
{{ form_row(field) }}
</td>
{% endfor %}
{% endblock %}
{% block website_body %}
<div class="row">
<div class="col-lg-12">
<div class="panel panel-default">
<div class="panel-body">
{{ form_start(form) }}
<div class="row">
<div class="col-lg-6">
{{ form_row(form.shop.name) }}
{{ form_row(form.shop.accountNumber) }}
{{ form_row(form.shop.email) }}
{{ form_row(form.shop.addressLine1) }}
</div>
<div class="col-lg-6">
{{ form_row(form.shop.addressLine2) }}
{{ form_row(form.shop.town) }}
{{ form_row(form.shop.county) }}
{{ form_row(form.shop.postcode) }}
</div>
</div>
<div class="row">
<h3>Missing Items</h3>
<table class="table missing_items">
<tbody class="missing_items" data-prototype="{{ form_row(form.missing_items.vars.prototype)|e('html_attr') }}"></tbody>
</table>
</div>
<div class="row">
<div class="col-lg-6">
{{ form_row(form.purchase.receivedReplacement) }}
</div>
<table class="table replacement-items">
<tbody class="replacement_items" data-prototype="{{ form_row(form.replaced_items.vars.prototype)|e('html_attr') }}"></tbody>
</table>
</div>
<div class="row">
<div class="col-lg-6">
{{ form_row(form.submit) }}
</div>
</div>
{{ form_end(form) }}
{% embed 'form/components/terms_and_conditions.html.twig' %}{% endembed %}
</div>
</div>
</div>
</div>
{% endblock %}
如有任何帮助,我们将不胜感激!尽一切努力将错误放在正确的位置。
所以对于其他人来说,我已经找到了这个难题的答案。
基本上,当我的 JS 通过 <tbody>
上的 "prototype" 属性将表单呈现到页面上时,据 Symfony 所知,我并没有明确地将字段输出到我的模板中.因此,在模板末尾调用“form_end(form)
”时,项目字段的所有错误都会被吐出。
当 form_end(form)
在幕后调用 form_rest()
时,它基本上会输出尚未显式呈现的表单的任何字段 - 因此验证错误及其各自的字段正在在页面的表单末尾输出!
通过在模板中显式输出这些字段,错误和相关字段在表单中正确显示;
<tbody class="missing_items" data-prototype="{{ form_row(form.missing_items.vars.prototype)|e('html_attr') }}">
{% for field in form.missing_items %}
<tr class="item">
<td>{{ form_row(field.quantity) }}</td>
<td>{{ form_row(field.description) }}</td>
<td>{{ form_row(field.invoiceNumber) }}</td>
<td>{{ form_row(field.invoiceDate) }}</td>
<td>{{ form_row(field.deliveryDate) }}</td>
</tr>
{% endfor %}
</tbody>
我希望这能帮助其他遇到同样困境的人!
我对 Symfony 表单集合字段有疑问。我有一个父表单,其中有两个字段是表单集合。一切都工作得很好,除非我提交带有无效数据的表单。表单集合字段的错误输出在页面的表单下方。我一直在阅读有关这些字段的 error_bubbling 的文档,并意识到对于 CollectionType 字段,它默认为 true。因此,我在每个字段上将其设置为 false,但错误仍未映射到表单上的字段。
集合字段可以通过前端javascript动态添加到页面中。我注意到,在我的标记中,在我提交表单之前,有两个错误的 <div class=""form-group">
添加到我的标记的基础上,我没有在我的模板中输出。当提交表单但无效时,将在这些 div 中输出错误。
代码;
ItemFormType;
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('shop', ShopType::class, [
'data_class' => Shop::class,
'label' => false,
])
->add('purchase', PurchaseType::class, [
'data_class' => Purchase::class,
'label' => false,
])
->add('missing_items', CollectionType::class, [
'entry_type' => MissingItemFormType::class,
'allow_add' => true,
'allow_delete' => true,
'label' => false,
'prototype' => true,
'error_bubbling' => false,
])
->add('replaced_items', CollectionType::class, [
'entry_type' => ReplacedItemFormType::class,
'allow_add' => true,
'allow_delete' => true,
'label' => false,
'prototype' => true,
'error_bubbling' => false,
])
->add('submit', SubmitType::class)
->getForm();
}
/**
* Get the form name.
*
* @return string
*/
public function getName(): string
{
return 'missing_form';
}
/**
* Set form options.
*
* @param OptionsResolver $resolver
*
* @return void
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => null,
'error_bubbling' => false
]);
}
控制器;
/**
* @Route("/", name="homepage")
*
* @param ClaimMailer $mailer
* @param Request $request
*
* @return Response
*/
public function indexAction(ClaimMailer $mailer, Request $request): Response
{
$purchase = [
'shop' => new Shop(),
'purchase' => new Purchase(),
];
$form = $this->createForm(MissingFormType::class, $purchase);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$this->store($form, $purchase);
// Send confirmation email.
$mailer->send(
$purchase['purchase']->getEmail(),
$purchase['shop']->getName(),
$purchase['purchase']->getClaimReferenceNumber()
);
return $this->render('form/form_complete.html.twig', [
'purchase_id' => $purchase['purchase']->getPurchaseReferenceNumber(),
]);
}
return $this->render('form/purchase_form.html.twig', [
'form' => $form->createView(),
]);
}
/**
* Store form data.
*
* @param Form $form
* @param array$claim
*
* @return void
*/
public function store(Form $form, $purchase){}
模板;
{% block _missing_form_missing_items_entry_row %}
{% for field in form %}
<td>
{{ form_row(field) }}
</td>
{% endfor %}
{% endblock %}
{% block _missing_form_replaced_items_entry_row %}
{% for field in form %}
<td>
{{ form_row(field) }}
</td>
{% endfor %}
{% endblock %}
{% block website_body %}
<div class="row">
<div class="col-lg-12">
<div class="panel panel-default">
<div class="panel-body">
{{ form_start(form) }}
<div class="row">
<div class="col-lg-6">
{{ form_row(form.shop.name) }}
{{ form_row(form.shop.accountNumber) }}
{{ form_row(form.shop.email) }}
{{ form_row(form.shop.addressLine1) }}
</div>
<div class="col-lg-6">
{{ form_row(form.shop.addressLine2) }}
{{ form_row(form.shop.town) }}
{{ form_row(form.shop.county) }}
{{ form_row(form.shop.postcode) }}
</div>
</div>
<div class="row">
<h3>Missing Items</h3>
<table class="table missing_items">
<tbody class="missing_items" data-prototype="{{ form_row(form.missing_items.vars.prototype)|e('html_attr') }}"></tbody>
</table>
</div>
<div class="row">
<div class="col-lg-6">
{{ form_row(form.purchase.receivedReplacement) }}
</div>
<table class="table replacement-items">
<tbody class="replacement_items" data-prototype="{{ form_row(form.replaced_items.vars.prototype)|e('html_attr') }}"></tbody>
</table>
</div>
<div class="row">
<div class="col-lg-6">
{{ form_row(form.submit) }}
</div>
</div>
{{ form_end(form) }}
{% embed 'form/components/terms_and_conditions.html.twig' %}{% endembed %}
</div>
</div>
</div>
</div>
{% endblock %}
如有任何帮助,我们将不胜感激!尽一切努力将错误放在正确的位置。
所以对于其他人来说,我已经找到了这个难题的答案。
基本上,当我的 JS 通过 <tbody>
上的 "prototype" 属性将表单呈现到页面上时,据 Symfony 所知,我并没有明确地将字段输出到我的模板中.因此,在模板末尾调用“form_end(form)
”时,项目字段的所有错误都会被吐出。
当 form_end(form)
在幕后调用 form_rest()
时,它基本上会输出尚未显式呈现的表单的任何字段 - 因此验证错误及其各自的字段正在在页面的表单末尾输出!
通过在模板中显式输出这些字段,错误和相关字段在表单中正确显示;
<tbody class="missing_items" data-prototype="{{ form_row(form.missing_items.vars.prototype)|e('html_attr') }}">
{% for field in form.missing_items %}
<tr class="item">
<td>{{ form_row(field.quantity) }}</td>
<td>{{ form_row(field.description) }}</td>
<td>{{ form_row(field.invoiceNumber) }}</td>
<td>{{ form_row(field.invoiceDate) }}</td>
<td>{{ form_row(field.deliveryDate) }}</td>
</tr>
{% endfor %}
</tbody>
我希望这能帮助其他遇到同样困境的人!