Одна информация не восстанавливается после отправки формы

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 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 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-разметка Twig сгенерированной формы:

<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 атрибутом).
  • 0
    @julmot, я использую Ajax JavaScript для обновления поля формы назначения в соответствии с текущим выбором в поле страны, и я использую СОБЫТИЯ для выбора городов. Вот пример в документации. ( symfony.com/doc/current/cookbook/form/… )
Теги:

3 ответа

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>

Я выложил его за стол, и теперь он отлично работает. есть ли какие-либо объяснения?

1

Это не работает, потому что вы не можете иметь HTML-элемент form внутри элемента tr HTML. Элемент tr может содержать только td и th элементов, в соответствии со спецификацией W3C - см. Разрешенное содержимое элемента tr в HTML5.

Это проблема, аналогичная той, что упоминается здесь в разделе стандартов W3C - разметка нарушена. См. Информацию о разметке таблиц в стандартах HTML W3C.

Более того, у вас есть элемент form непосредственно внутри элемента tr, но вы также не закрываете последний тег td после кнопки отправки, что, я полагаю, также имеет отношение к проблеме.

Ваша разметка является источником всех проблем, я не знаю, мог ли какой-либо браузер правильно обрабатывать такой код. Уверены все проверки через валидатор W3C, а затем вы можете искать проблемы в контроллерах и др. Недопустимый код HTML может быть источником многих неожиданных проблем, которые затем трудно отлаживать, и вы часто окажетесь в неправильном месте. И я говорю из опыта здесь.

  • 0
    @hous Я добавил ваш пример кода Twig из вашего ответа на исходный вопрос, я думаю, что он также будет присутствовать там для более легкой ссылки (редактирование может быть еще не видно из-за проходящего процесса рецензирования StackOverflow).
  • 0
    но почему все чужие входы восстанавливаются, кроме «места назначения»? Вы не думаете, что это имеет отношение к коду JavaScript? success: function (html) { $('#city').replaceWith( $(html).find('#city') );
Показать ещё 1 комментарий
0

Прежде всего, лучше использовать отдельное действие контроллера только для того, чтобы получить нужные вам города и заменить только опции в поле выбора. Рендеринг всей формы с разбивкой на страницы и т.д. Немного перебор. Во-вторых, проверьте, что именно вы получили как html от вашего вызова ajax, особенно если вход, выбранный $ (html).find('# city'), содержит атрибут 'name'. Недостающее значение из представленной формы не имеет ничего общего с самой платформой Symfony2, все о правильном содержании HTML.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню