Sirius
Sirius

Reputation: 653

Instant search with Ajax and Symfony2

I have create a search filter that works nicely without ajax and javascript, but to get the result the user have to click on the search button. I would like to get the result while the user type.

This is what I have done:

Routing.yml

searchFlight:
    path: /search_flight
    defaults:  {  _controller: FLYBookingsBundle:Post:searchtabflightResult }

Controller

    /**
 *
 * @Route("/search_flight", name="searchFlight")
 * @Method("POST")
 */
public function searchtabflightResultAction(Request $request)
{
    $form = $this->createForm(new SearchflightType());
    $request->request->get('query');
        $form->handleRequest($request);
        dump($form);
        $em = $this->getDoctrine()->getManager();
        $entities = $em->getRepository('FLYBookingsBundle:Post')->searchflight($form);




    if ($request->isXmlHttpRequest()) {
        $jsonArray = json_encode(array(
            'status' => 'success', 'entities' => $form
        ));
        $response = new Response($jsonArray);
        return $response;

    }

    return $this->render('FLYBookingsBundle:Post:searchtabflightResult.html.twig', array(
        'form' => $form->createView(),
        'entities' => $entities,
        ));
}

searchtabflightresult.html.twig

<form id="myForm" action="{{ path ('searchFlight') }}" method="POST">

 {{ form_widget(form.from, { 'attr': {'class': 'form-control auto',} }) }}
 {{ form_errors(form.from) }}

 {{ form_widget(form.to, { 'attr': {'class': 'form-control auto1',} }) }}
 {{ form_errors(form.to) }}

 {{ form_widget(form.departuredate) }}
 {{ form_errors(form.departuredate) }}

 {{ form_widget(form.arrivaldate) }}
 {{ form_errors(form.arrivaldate) }}

 {{ form_widget(form.price) }}
 {{ form_errors(form.price) }}

<button style="height: 43px" type="submit" class="full-width icon-check">SEARCH NOW</button>

</form>


      <div class="reloadproducts">

      <i id="spinner" style="display:none; font-size: 20px" class="fa fa-spinner fa-pulse fa-2x fa-fw"></i>

      {% if entities|length != 0 %}
      {% for entity in entities %}

      {{ entity.from }}
      {{ entity.to }}
      {{ entity.price|tva(entity.tva.multiplicate) }}
      {% if entity.departuredate %}{{ entity.departuredate|date('Y-m-d H:i:s') }}{% endif %}
      {% if entity.arrivaldate %}{{ entity.arrivaldate|date('Y-m-d H:i:s') }}

      {% endif %} 

      {% endfor %}

      {% else %}
      <h1 style="color: #707070">The product you loking for doesn't exist</h1>
      {% endif %} 

     </div>

.

    <script>
        $(document).ready(function() {
            $("#myForm").submit(function(e) {
                $('#spinner').show();
                e.preventDefault();
                var $form = $('#myForm');

                $.ajax({
                    type: "POST",
                    dataType: "json",
                    data: $form.serialize(),
                    cache: false,
                    success: function(response) {
                        $('.reloadproducts').load(window.location + ' .reloadproducts >  *');
                        $('#spinner').hide();
                        console.log(response);
                    },
                    error: function(response) {
                        console.log(response);
                        $('#spinner').hide();
                    }
                });

            });
        });
    </script>

ADD:

class SearchflightType extends AbstractType
{

    public function buildForm(FormBuilderInterface $builder, array $options)
    {


        $builder



            ->add('from', 'genemu_jqueryselect2_entity', array(
                    'class' => 'FLYBookingsBundle:ListDeparturesArrivals',
                    'property' => 'name',
                    'placeholder' => 'Departure city',
                    'query_builder' => function(EntityRepository $er) {
                        return $er->createQueryBuilder('u')
                            ->where('u.mode_transport = :mode')
                            ->setParameter("mode", "AIRPLANE")
                            ->groupBy('u.code')
                            ->orderBy('u.name', 'ASC');
                    },)
            )
            ->add('to', 'genemu_jqueryselect2_entity', array(
                    'class' => 'FLYBookingsBundle:ListDeparturesArrivals',
                    'property' => 'name',
                    'placeholder' => 'Arrival city',
                    'query_builder' => function(EntityRepository $er) {
                        return $er->createQueryBuilder('u')
                            ->where('u.mode_transport = :mode')
                            ->setParameter("mode", "AIRPLANE")
                            ->groupBy('u.code')
                            ->orderBy('u.name', 'ASC');
                    },)
            )

            ->add('departuredate', DateType::class, array(
                'required' => false,
                'label' => 'Departure date',
                'format' => 'y/M/d',
                'widget' => 'single_text',
                'attr' => [
                    'class' => 'form-control date_timepicker_start input-inline',
                    'placeholder' => 'dd/mm/yyyy',
                ]
            ))
            ->add('arrivaldate', DateType::class, array(
                'required' => false,
                'label' => 'Arrival date',
                'format' => 'y/M/d',
                'widget' => 'single_text',
                'attr' => [
                    'class' => 'form-control date_timepicker_end input-inline',
                    'placeholder' => 'dd/mm/yyyy',
                ]
    ))


            ->add('price', TextType::class, array(
                'required' => false,
                'attr' => [
                    'class'             => 'range',
                    "data-slider-min"   => "5",
                    "data-slider-max"   => "1000",
                    "data-slider-step"  => "0.5",
                    "data-slider-value" => "[5,1000]"
                ]
            ));

    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
{
    parent::setDefaultOptions($resolver);
    $resolver->setDefaults(array(
        // avoid to pass the csrf token in the url (but it's not protected anymore)
        'csrf_protection' => false,
        'data_class' => 'FLY\BookingsBundle\Entity\Post'
    ))

    ;
}

public function getName()
{
    return 'fly_bookingsbundle_searchtabflight';
}
}

Upvotes: 0

Views: 677

Answers (1)

Andrey Kazmerchuk
Andrey Kazmerchuk

Reputation: 101

Just want to give you some advices.

First of all, if you want to get the result while the user typing, use 'keyup' method.

Don't use

if ($this->get('request')->getMethod() == 'POST')

If you want to use this method only for POST, use annotation @Method, example here

And if you use

dataType: "json",

return JsonResponse from controller, for example:

    return JsonResponse::create('status' => 'success', 'entities' => $form);

You don't need to set headers and do json_encode in this case. Last point maybe helps you with your problem. Good luck!

UPDATE:

$('#myForm > input').change(function(e) {
            $('#spinner').show();
            e.preventDefault();

            if (xhr) {
                xhr.abort();
                xhr = null;
            }

            var xhr = $.ajax({
                type: "POST",
                dataType: "json",
                data: $form.serialize(),
                cache: false,
                success: function(response) {
                    $('.reloadproducts').load(window.location + ' .reloadproducts >  *');
                    $('#spinner').hide();
                    console.log(response);
                },
                error: function(response) {
                    console.log(response);
                    $('#spinner').hide();
                }
            });

        });

Upvotes: 1

Related Questions