2015-02-23 33 views
0

我正嘗試創建搜索表單。在這個表格中,我有兩個選擇框,一個用於國家,另一個用於名爲「目的地」的城市。第二個取決於選定的國家。我也有其他一些投入。提交表單後無法恢復一個數據

選擇國家後,使用ajax查詢正確顯示與其相關的所有城市。

問題是如果我選擇一個國家並提交表單,目的地不會在地址欄中恢復,但如果我不選擇國家/地區,目的地將會恢復。

這是我聽不懂沒有選擇國家

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

地址欄的顯示,這是,如果我選擇一個國家的地址欄的顯示方式。正如你所看到的目標是缺少

/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, 
    )); 

} 

這是生成的表單的嫩枝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> 

我已經把它在表外,現在工作得很好。有什麼解釋嗎?

+0

您是否在使用AJAX顯示相關城市?如果是這樣,請提供用於顯示相關城市的JavaScript。在選擇城市之後,請檢查您是否可以使用JavaScript接收選定的選項。如果您無法通過JavaScript接收選中的選擇選項,請檢查在DOM中選擇城市後腳本將發生的變化。它可以是,它只會改變一個類或屬性來顯示選擇內容,但是它不會檢查選項(例如使用'checked'屬性)。 – dude 2015-02-23 22:36:53

+0

@julmot,我使用Ajax JavaScript根據國家/地區字段中的當前選擇更新目的地表單字段,並使用EVENTS選擇城市。以下是文檔中的示例。 (http://symfony.com/doc/cookbook/form/dynamic_form_modification.html#cookbook-form-events-submitted-data) – hous 2015-02-24 10:28:24

回答

0

問題是因爲表單到表這樣

<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> 

我已經把它外,現在工作得很好。有沒有解釋?

0

首先,更好地使用單獨的控制器操作來檢索您需要的城市,並僅替換選擇字段中的選項。用分頁等渲染整個表單有點矯枉過正。 其次,檢查你從ajax調用得到的html究竟是什麼,尤其是$(html).find('#city')選擇的輸入是否包含'name'屬性。從提交的表單中缺少的值與Symfony2框架本身沒有什麼共同之處,都是關於正確的HTML內容。

1

它不起作用,因爲您不能在trHTML元素中使用formHTML元素。根據W3C規範,tr元素只能包含tdth元素 - 請參閱permitted contents of the tr element in HTML5

這是一個與W3C標準部分中提到的問題類似的問題 - 標記已損壞。見unexpected table markup informations in the W3C HTML standards

而且,並不是只有你有form直接在tr元素中的元素,但你也不要你的提交按鈕,我想,有什麼做的問題,也是後關閉最後td標籤。

您的標記是所有問題的來源,我不知道任何瀏覽器是否可以正確處理此類代碼。通過W3C驗證器驗證所有內容,然後您可以在控制器等中搜索問題。無效的HTML代碼可能是許多意想不到的問題的根源,而這些問題很難調試,並且您通常最終會在錯誤的地方搜索。我在這裏講述了經驗。

+0

@hous我已經添加了您的答案的原始問題的Twig示例代碼,我認爲它也應該存在,以便於參考(由於正在進行StackOverflow同行評審過程,編輯可能不會顯示)。 – XanatosLightfiren 2015-02-24 20:19:32

+0

但爲什麼除非「目的地」,所有其他輸入都會被重新採集?你不覺得它與JavaScript代碼有關係嗎? '成功:功能(HTML){ $('#城市)replaceWith( $(HTML).find('#城市) );' – hous 2015-02-25 13:12:06

+0

@hous它可能是這樣,但只。因爲HTML無效。可能#city字段沒有被找到(在響應中),所以它可能被替換爲空值。有效的HTML代碼是開始尋找其他問題最重要的 - 然後您可能會開始調試您的JS代碼。你自己寫道,當你糾正HTML結構時,一切都開始按預期工作 - 所以也許這兩件事情實際上是相連的,但這一切都歸結爲HTML首先是無效的,在我看來。 – XanatosLightfiren 2015-02-28 13:56:09