提交表单后未恢复一项数据
One data is not recovered after submit form
我正在尝试创建一个搜索表单。在此表格中,我有两个 select 框,一个用于国家,第二个用于名为 "destination" 的城市。第二个取决于 selected 国家。我也有一些其他的输入。
在 select 一个国家之后,使用 ajax 查询可以正确显示与其相关的所有城市。
问题是,如果我选择一个国家并提交表格,目的地不会在地址栏中恢复,但如果我不select一个国家,目的地将被恢复。
如果我不select一个国家
,地址栏就是这样显示的
/q?title=&country=&destination=&airport=&departureDate=&returnDate=&price=
这就是我 select 一个国家时地址栏的显示方式。如您所见,目的地丢失
/q?title=&country=1&airport=&departureDate=&returnDate=&price=
注意 我正在使用类似的表格和方法 POST 来创建或编辑新的旅行,它工作正常
SearchTravelType
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormEvent;
//........
use Symfony\Component\Form\FormInterface;
use AppBundle\Entity\Country;
class SearchTravelType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
->add('country', 'entity', array(
'required' => true,
'class' => 'AppBundle:Country',
'property' => 'en',
'multiple' => false,
'expanded' => false,
'label' => 'ِCountry',
'empty_value' => '' ))
//....
$formModifier = function (FormInterface $form, Country $country = null) {
$cities = null === $country ? array() : $country->getCities();
$form->add('destination', 'entity', array(
'class' => 'AppBundle:CityWorld',
'choices' => $cities,
'multiple' => false,
'expanded' => false,
'property' => 'name',
'label' => 'Destination'));
};
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
function (FormEvent $event) use ($formModifier) {
// this would be your entity
$data = $event->getData();
$formModifier($event->getForm(), $data->getCountry());
}
);
$builder->get('country')->addEventListener(
FormEvents::POST_SUBMIT,
function (FormEvent $event) use ($formModifier) {
// It's important here to fetch $event->getForm()->getData(), as
// $event->getData() will get you the client data (that is, the ID)
$country = $event->getForm()->getData();
// since we've added the listener to the child, we'll have to pass on
// the parent to the callback functions!
$formModifier($event->getForm()->getParent(), $country);
}
);
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Travel'
));
}
public function getName()
{
return null;
}
}
这是表格和javascript代码
<form method="get" action="" class="form-horizontal" role="form" >
{{ form_widget(form.country, { 'id': 'country' }) }}
{{ form_widget(form.destination, { 'id': 'city' }) }}
//.............
</form>
<script type="text/javascript">
var $county = $('#country');
$county.change(function () {
// ... retrieve the corresponding form.
var $form = $(this).closest('form');
var data = {};
data[$county.attr('name')] = $county.val();
// Submit data via AJAX to the form's action path.
$.ajax({
url: '{{ path('dashboard_travel_search', {'agence_slug': agence.slug}) }}',
type: 'POST', data: data,
success: function (html) {
$('#city').replaceWith(
// ... with the returned one from the AJAX response.
$(html).find('#city')
);
}
});
});
这是控制器
/**
* @ParamConverter("agence", options={"mapping": {"agence_slug":"slug"}})
*/
public function searchAction(Request $request, Agence $agence)
{
if (false === $this->get('security.context')->isGranted('view', $agence)) {
throw new AccessDeniedException('Unauthorised access!');
}
/* Instantiate Travel to not get this error
Error: Call to a member function getCountry() on a non-object
*/
$travel = new Travel();
$form = $this->createForm(new SearchTravelType(), $travel);
if ($request->getMethod() == 'POST' ) {
$form->handleRequest($request);
}
$em = $this->getDoctrine()->getManager();
$paginator = $this->get('knp_paginator');
$title = $request->query->get('title');
$country = $request->query->get('country');
$destination = $request->query->get('destination');
$price = $request->query->get('price');
$departureDate = $request->query->get('departureDate');
$returnDate = $request->query->get('returnDate');
$nbDays = $request->query->get('nbDays');
$nbNights = $request->query->get('nbNights');
$airport = $request->query->get('airport');
$enabled = $request->query->get('enabled');
$qb = $em->getRepository('AppBundle:Travel')->getListSearchTravelsDashboard($agence, $title, $country, $destination, $price, $departureDate, $returnDate, $nbDays, $nbNights, $airport, $enabled);
$pagination = $paginator->paginate(
$qb,
$request->query->get('page', 1), 10);
$pagination->setSortableTemplate('KnpPaginatorBundle:Pagination:sortable_link_dashboard.html.twig');
return $this->render('AppBundle:Dashboard/Travel:list-search.html.twig', array(
'pagination' => $pagination,
'form' => $form->createView(),
'agence' => $agence,
));
}
这是生成表单的 Twig HTML 标记:
<table id="sample-table-1" class="table table-responsives table-striped table-hover">
<tr>
<form class="form-inline" role="form" method="get" action="">
<td class="center">-</td>
<td>{{ form_widget(form.title) }}</td>
<td>{{ form_widget(form.country, { 'id': 'country' }) }}</td>
<td>{{ form_widget(form.destination, { 'id': 'city' }) }}</td>
<td>{{ form_widget(form.airport) }}</td>
<td>{{ form_widget(form.departureDate) }}</td>
<td>{{ form_widget(form.returnDate) }}</td>
<td>{{ form_widget(form.price) }}</td>
<td>{{ form_widget(form.nbDays) }}</td>
<td>{{ form_widget(form.nbNights) }}</td>
<td>{{ form_widget(form.enabled) }} {{ form_rest(form) }}</td>
<td><span class="input-group-btn">
<button type="submit" class="btn btn-purple btn-sm" title="Rechercher">
<i class="icon-search bigger-110"></i></button>
</span>
</form>
</tr>
我已经把它放在 table 外面了,现在可以正常使用了。有什么解释吗?
首先,最好使用单独的控制器操作来检索您需要的城市,并仅替换 select 字段中的选项。用分页等渲染整个表单有点矫枉过正。
其次,检查您从 ajax 调用中作为 html 到底得到了什么,特别是输入 select 是否由 $(html).find('#city' ) 包含 'name' 属性。提交表单中的缺失值与 Symfony2 框架本身没有任何共同之处,都是关于正确的 HTML 内容。
问题是因为表单 变成了这样的 table
<table id="sample-table-1" class="table table-responsives table-striped table-hover">
<tr>
<form class="form-inline" role="form" method="get" action="">
<td class="center">-</td>
<td>{{ form_widget(form.title) }}</td>
<td>{{ form_widget(form.country, { 'id': 'country' }) }}</td>
<td>{{ form_widget(form.destination, { 'id': 'city' }) }}</td>
<td>{{ form_widget(form.airport) }}</td>
<td>{{ form_widget(form.departureDate) }}</td>
<td>{{ form_widget(form.returnDate) }}</td>
<td>{{ form_widget(form.price) }}</td>
<td>{{ form_widget(form.nbDays) }}</td>
<td>{{ form_widget(form.nbNights) }}</td>
<td>{{ form_widget(form.enabled) }} {{ form_rest(form) }}</td>
<td><span class="input-group-btn">
<button type="submit" class="btn btn-purple btn-sm" title="Rechercher">
<i class="icon-search bigger-110"></i></button>
</span>
</form>
</tr>
我已将它放在 table 之外,现在可以正常使用了。有什么解释吗?
它不起作用,因为您不能在 tr
HTML 元素中包含 form
HTML 元素。根据 W3C 规范,tr
元素内部只能包含 td
和 th
元素 - 请参阅 permitted contents of the tr
element in HTML5.
这是一个类似于 W3C 标准部分中提到的问题 - 标记已损坏。参见 unexpected table markup informations in the W3C HTML standards。
此外,不仅 form
元素直接位于 tr
元素内,而且您也没有关闭提交按钮后的最后一个 td
标记,其中,我想,也与这个问题有关。
您的标记是所有问题的根源,我不知道是否有浏览器可以正确处理此类代码。通过 W3C 验证器验证所有内容,然后您可以在控制器等中搜索问题。无效的 HTML 代码可能是许多意想不到的问题的根源,这些问题很难调试,而且您经常会在错误的地方搜索。我说的是这里的经验。
我正在尝试创建一个搜索表单。在此表格中,我有两个 select 框,一个用于国家,第二个用于名为 "destination" 的城市。第二个取决于 selected 国家。我也有一些其他的输入。
在 select 一个国家之后,使用 ajax 查询可以正确显示与其相关的所有城市。
问题是,如果我选择一个国家并提交表格,目的地不会在地址栏中恢复,但如果我不select一个国家,目的地将被恢复。
如果我不select一个国家
,地址栏就是这样显示的/q?title=&country=&destination=&airport=&departureDate=&returnDate=&price=
这就是我 select 一个国家时地址栏的显示方式。如您所见,目的地丢失
/q?title=&country=1&airport=&departureDate=&returnDate=&price=
注意 我正在使用类似的表格和方法 POST 来创建或编辑新的旅行,它工作正常
SearchTravelType
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormEvent;
//........
use Symfony\Component\Form\FormInterface;
use AppBundle\Entity\Country;
class SearchTravelType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
->add('country', 'entity', array(
'required' => true,
'class' => 'AppBundle:Country',
'property' => 'en',
'multiple' => false,
'expanded' => false,
'label' => 'ِCountry',
'empty_value' => '' ))
//....
$formModifier = function (FormInterface $form, Country $country = null) {
$cities = null === $country ? array() : $country->getCities();
$form->add('destination', 'entity', array(
'class' => 'AppBundle:CityWorld',
'choices' => $cities,
'multiple' => false,
'expanded' => false,
'property' => 'name',
'label' => 'Destination'));
};
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
function (FormEvent $event) use ($formModifier) {
// this would be your entity
$data = $event->getData();
$formModifier($event->getForm(), $data->getCountry());
}
);
$builder->get('country')->addEventListener(
FormEvents::POST_SUBMIT,
function (FormEvent $event) use ($formModifier) {
// It's important here to fetch $event->getForm()->getData(), as
// $event->getData() will get you the client data (that is, the ID)
$country = $event->getForm()->getData();
// since we've added the listener to the child, we'll have to pass on
// the parent to the callback functions!
$formModifier($event->getForm()->getParent(), $country);
}
);
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Travel'
));
}
public function getName()
{
return null;
}
}
这是表格和javascript代码
<form method="get" action="" class="form-horizontal" role="form" >
{{ form_widget(form.country, { 'id': 'country' }) }}
{{ form_widget(form.destination, { 'id': 'city' }) }}
//.............
</form>
<script type="text/javascript">
var $county = $('#country');
$county.change(function () {
// ... retrieve the corresponding form.
var $form = $(this).closest('form');
var data = {};
data[$county.attr('name')] = $county.val();
// Submit data via AJAX to the form's action path.
$.ajax({
url: '{{ path('dashboard_travel_search', {'agence_slug': agence.slug}) }}',
type: 'POST', data: data,
success: function (html) {
$('#city').replaceWith(
// ... with the returned one from the AJAX response.
$(html).find('#city')
);
}
});
});
这是控制器
/**
* @ParamConverter("agence", options={"mapping": {"agence_slug":"slug"}})
*/
public function searchAction(Request $request, Agence $agence)
{
if (false === $this->get('security.context')->isGranted('view', $agence)) {
throw new AccessDeniedException('Unauthorised access!');
}
/* Instantiate Travel to not get this error
Error: Call to a member function getCountry() on a non-object
*/
$travel = new Travel();
$form = $this->createForm(new SearchTravelType(), $travel);
if ($request->getMethod() == 'POST' ) {
$form->handleRequest($request);
}
$em = $this->getDoctrine()->getManager();
$paginator = $this->get('knp_paginator');
$title = $request->query->get('title');
$country = $request->query->get('country');
$destination = $request->query->get('destination');
$price = $request->query->get('price');
$departureDate = $request->query->get('departureDate');
$returnDate = $request->query->get('returnDate');
$nbDays = $request->query->get('nbDays');
$nbNights = $request->query->get('nbNights');
$airport = $request->query->get('airport');
$enabled = $request->query->get('enabled');
$qb = $em->getRepository('AppBundle:Travel')->getListSearchTravelsDashboard($agence, $title, $country, $destination, $price, $departureDate, $returnDate, $nbDays, $nbNights, $airport, $enabled);
$pagination = $paginator->paginate(
$qb,
$request->query->get('page', 1), 10);
$pagination->setSortableTemplate('KnpPaginatorBundle:Pagination:sortable_link_dashboard.html.twig');
return $this->render('AppBundle:Dashboard/Travel:list-search.html.twig', array(
'pagination' => $pagination,
'form' => $form->createView(),
'agence' => $agence,
));
}
这是生成表单的 Twig HTML 标记:
<table id="sample-table-1" class="table table-responsives table-striped table-hover">
<tr>
<form class="form-inline" role="form" method="get" action="">
<td class="center">-</td>
<td>{{ form_widget(form.title) }}</td>
<td>{{ form_widget(form.country, { 'id': 'country' }) }}</td>
<td>{{ form_widget(form.destination, { 'id': 'city' }) }}</td>
<td>{{ form_widget(form.airport) }}</td>
<td>{{ form_widget(form.departureDate) }}</td>
<td>{{ form_widget(form.returnDate) }}</td>
<td>{{ form_widget(form.price) }}</td>
<td>{{ form_widget(form.nbDays) }}</td>
<td>{{ form_widget(form.nbNights) }}</td>
<td>{{ form_widget(form.enabled) }} {{ form_rest(form) }}</td>
<td><span class="input-group-btn">
<button type="submit" class="btn btn-purple btn-sm" title="Rechercher">
<i class="icon-search bigger-110"></i></button>
</span>
</form>
</tr>
我已经把它放在 table 外面了,现在可以正常使用了。有什么解释吗?
首先,最好使用单独的控制器操作来检索您需要的城市,并仅替换 select 字段中的选项。用分页等渲染整个表单有点矫枉过正。 其次,检查您从 ajax 调用中作为 html 到底得到了什么,特别是输入 select 是否由 $(html).find('#city' ) 包含 'name' 属性。提交表单中的缺失值与 Symfony2 框架本身没有任何共同之处,都是关于正确的 HTML 内容。
问题是因为表单 变成了这样的 table
<table id="sample-table-1" class="table table-responsives table-striped table-hover">
<tr>
<form class="form-inline" role="form" method="get" action="">
<td class="center">-</td>
<td>{{ form_widget(form.title) }}</td>
<td>{{ form_widget(form.country, { 'id': 'country' }) }}</td>
<td>{{ form_widget(form.destination, { 'id': 'city' }) }}</td>
<td>{{ form_widget(form.airport) }}</td>
<td>{{ form_widget(form.departureDate) }}</td>
<td>{{ form_widget(form.returnDate) }}</td>
<td>{{ form_widget(form.price) }}</td>
<td>{{ form_widget(form.nbDays) }}</td>
<td>{{ form_widget(form.nbNights) }}</td>
<td>{{ form_widget(form.enabled) }} {{ form_rest(form) }}</td>
<td><span class="input-group-btn">
<button type="submit" class="btn btn-purple btn-sm" title="Rechercher">
<i class="icon-search bigger-110"></i></button>
</span>
</form>
</tr>
我已将它放在 table 之外,现在可以正常使用了。有什么解释吗?
它不起作用,因为您不能在 tr
HTML 元素中包含 form
HTML 元素。根据 W3C 规范,tr
元素内部只能包含 td
和 th
元素 - 请参阅 permitted contents of the tr
element in HTML5.
这是一个类似于 W3C 标准部分中提到的问题 - 标记已损坏。参见 unexpected table markup informations in the W3C HTML standards。
此外,不仅 form
元素直接位于 tr
元素内,而且您也没有关闭提交按钮后的最后一个 td
标记,其中,我想,也与这个问题有关。
您的标记是所有问题的根源,我不知道是否有浏览器可以正确处理此类代码。通过 W3C 验证器验证所有内容,然后您可以在控制器等中搜索问题。无效的 HTML 代码可能是许多意想不到的问题的根源,这些问题很难调试,而且您经常会在错误的地方搜索。我说的是这里的经验。