提交表单后不会恢复一个数据


One data is not recovered after submit form

我正在尝试创建一个搜索表单。在此表格中,我有两个选择框,一个用于国家/地区,第二个用于名为"目的地"的城市。第二个取决于所选国家。我还有一些其他的输入。

选择国家/地区后,将使用 ajax 查询正确显示与其相关的所有城市。

问题是,如果我选择一个国家并提交表格,目的地不会在地址栏中恢复,但如果我不选择国家,目的地将被恢复。

这就是

我不选择国家/地区时地址栏的显示方式

/q?title=&country=&destination=&airport=&departureDate=&returnDate=&price=

这就是如果我选择一个国家/地区,地址栏的显示方式。如您所见,目的地丢失了

/q?title=&country=1&airport=&departureDate=&returnDate=&price=

注意我正在使用带有 POST 方法的类似表单来创建或编辑新的旅行,它工作正常

搜索旅行类型

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>

我把它放在桌子外面,现在工作正常。有什么解释吗?

它不起作用,因为tr HTML 元素中不能有form HTML 元素。根据 W3C 规范,tr 元素内部只能包含tdth元素 - 请参阅 HTML5 中 tr 元素的允许内容。

这是一个类似于 W3C 标准部分中提到的问题 - 标记已损坏。请参阅 W3C HTML 标准中意外的表标记信息。

此外,您不仅直接在tr元素中有一个form元素,而且您也不会在提交按钮之后关闭最后一个td标签,我想这也与问题有关。

您的标记是那里所有问题的根源,我不知道是否有任何浏览器可以正确处理此类代码。通过 W3C 验证器验证所有内容,然后您可以在控制器等中搜索问题。无效的HTML代码可能是许多意外问题的根源,这些问题很难调试,并且您最终通常会在错误的位置进行搜索。我在这里是根据经验说话的。

首先,最好使用单独的控制器操作来检索所需的城市并仅替换选择字段中的选项。用分页等渲染整个表单有点矫枉过正。其次,检查你从 ajax 调用中得到的 html 到底是什么,特别是 $(html(.find('#city'( 选择的输入是否包含 'name' 属性。提交表单中缺少的值与Symfony2框架本身没有任何共同之处,它都是关于正确的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>

我把它放在桌子外面,现在工作正常。 有什么解释吗?