Création d'une barre de recherche autocomplete en symfony 3

19/12/2017
écrit par: Overwatch

Nous allons voir ici comment utiliser le bundle pugx/autocompleter-bundle permettant d'avoir une autocompletion simple sur un champs de recherche.

1 ) Installation du bundle avec composer

composer require pugx/autocompleter-bundle 

 

2 ) Dans appeKernel.php ajoutez

new PUGX\AutocompleterBundle\PUGXAutocompleterBundle()

 

3 )  Sur votre twig base.html.twig ajoutez ce dont le bundle a besoin, ici il faut rajouter jquery-ui et le script adapté pour l'autocomplétion

 <script src="//code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
<script src="{{ asset('bundles/pugxautocompleter/js/autocompleter-jqueryui.js') }}"></script>


 

4 ) Rajouter ces éléments pour loader l'autocompleter sur le formulaire adéquat au niveau de votre fichier javascript, app.js par exemple à la racine web de votre projet.

$(document).ready(function () {
  'use strict';
  $('#form_titre').autocompleter({
    url_list: '/search-article',
    url_get: '/?term='
  });


  $("#ui-id-1").click(function(){
    var id = $("#form_titre").val();

    if(id.toString().length > 0){
      $(location).attr('href', '/article/'+id.toString());
    }
  })

}); 
  

 

5) Créer le formulaire que vous avez besoin, Form.html.twig  Nous allons utiliser l'entité "Article" et son FormType pour l'exemple

namespace AppBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use PUGX\AutocompleterBundle\Form\Type\AutocompleteType;
use Symfony\Component\OptionsResolver\OptionsResolver;


class ArticleType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('titre', AutocompleteType::class, ['class' => 'AppBundle:Article']);
    }


    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => 'AppBundle\Entity\Article',
        ]);
    }
}

Nous créons ensuite le twig adapté

{% include "base.html.twig" %}
{% block search %}
    {{ form_start(form) }}
    {{ form_widget(form) }}
    {{ form_end(form) }}
{% endblock %} 

6) rajouter ce json qui sera loader par le script autocomplete search.json.twig 

[{% for article in articles -%}
    {{ {value: article.id, label: article.titre}|json_encode|raw }}
    {%- if not loop.last %},{% endif -%}
    {%- endfor %}] 

7 )  Dans votre controller rajouter le modèle sur lequel vous souhaitez lancer la recherche et rajoutez le champs nécessaire, dans cet exemple "Article".

public function searchAction()
{
    $article = new  Article();

    $form = $this->createFormBuilder( $article, array(
        'action' => $this->generateUrl('homepage').'?term=',
        'method' => 'GET',
    ) )
        ->add('titre', null, ['label' => ' Barre de recherche'] )
        ->getForm();


    return $this->render(':default/Form.html.twig', ['form' => $form->createView() ]);
}

Nous Rajouter dans l'entité la requête adapté à la recherche, ici un exemple simple qui peut être totalement revu :)

namespace AppBundle\Repository;

/**
 * articleRepository
 *
 * This class was generated by the Doctrine ORM. Add your own custom
 * repository methods below.
 */
class ArticleRepository extends \Doctrine\ORM\EntityRepository
{
    /**
     * @param string $titre
     *
     * @return array
     */
    public function findLike($titre)
    {
        return $this
            ->createQueryBuilder('a')
            ->where('a.titre LIKE :titre')
            ->setParameter( 'titre', "%$titre%")
            ->orderBy('a.titre')
            ->setMaxResults(5)
            ->getQuery()
            ->execute()
            ;
    }
}

8 ) Nous créons l'action dans le Controller de votre choix qui permettra de lancer la recherche et de l'afficher dans le json créé plus en amont.


/**
 * @Route("/search-article", name="search_article", defaults={"_format"="json"})
 * @Method("GET")
 */
public function searchArticleAction(Request $request)
{
    $q = $request->query->get('term'); // use "term" instead of "q" for jquery-ui
    $results = $this->getDoctrine()->getRepository('AppBundle:Article')->findLike($q);

    return $this->render(":default/search.json.twig", ['articles' => $results]);
}