Quoi donc ? Auto-complete ?

Un champ de texte auto-complete : Un truc genial qui permet de saisir une valeur dans une liste qui peut etre tres importante. Parce qu'une combo-list avec plusieurs centaines d'entrées, c'est vraiment insupportable. Heureusement ajax est là. Et donc voila un champ texte, quand on tape le debut d'une chaine, une liste avec des propositions correspondante va s'ouvrir automatiquement. L'effet est assez bluffant, essayez :

Allons y pour la recette de cuisine :

1 - Activer ajax dans notre application :

En fait on a besoin d'embarquer une librairie javascript pour pouvoir utiliser les fonctions ajax de Ruby On Rails. la chose est tres simple, il suffit d'ajouter la ligne qui suit dans le layout de la page. (pour moi c'est la vue : application.rhtml)

<%= javascript_include_tag :defaults %>

2 - Afficher le champ :

J'ai utilisé cette technique sur la gestion des personnes dans mon application. J'ai ajouté le champs de saisie sur la page liste, ce qui me permet de chercher directement une personne.

Voila donc ce que j'ai ajouté dans ma vue liste.rhtml :

<%= start_form_tag :action => 'search' %>
<div class="auto_complete">
    <%= text_field_with_auto_complete :search, :name, "size" => 20 %>
</div>
<%= image_submit_tag("icons/magnifier", :title => _('Search'),:class=>"image_to") %>
<%= end_form_tag %>@@
  • C'est a dire que j'ai crée un formulaire qui poste sur l'action search de mon controleur.
  • j'y ajoute ce fameux champ auto-complete, et un bouton submit.
  • La fin du formulaire, et hop le tour est joué.

[1]

3 - La reponse à la requete ajax :

Explication du phenomène : quand on tape du texte dans le champ, le navigateur va faire un requette http pour recuperer la liste à afficher. [2] cette requette dans notre cas, execute l'action du controleur qui correspond. La voici, dans le fichier people_controller.rb :

def auto_complete_for_search_name
	@people = Person.find(:all, 
	:conditions => [ 'LOWER(lastname) LIKE ?',
	'%' + params[:search][:name].downcase + '%' ], 
	:order => 'lastname ASC',
	:limit => 8)
	render :partial => "peoplelist" 
end
  • d'abord le nom de l'action : on n'a pas le choix : elle doit s'appeler auto_complete_objet_methode que j'ai mis en paramètre dans la méthode text_field_with_auto_complete.
  • ensuite on cherche la liste des propositions qui correspondent à la valeur du champs en cours : params[:objet][:method]
    • on met tout en minuscule pour la comparaison, afin que la recherche marche quelque soit la casse.
    • on ordonne les reponse dans l'ordre alphabetique.
    • on limite la reponse à huit propositions
  • enfin on renvoi la vue peoplelist avec notre liste de reponse.

4 - La vue de la liste des propositions :

on crée donc la vue peoplelist, nom du fichier : _peoplelist.rhtml

<ul class="ac_list"><% for person in @people do -%><li class="ac_fullname"><b><%=h person.lastname%></b> <%=h person.firstname %></li><br/><% end -%></ul>
  • ici on formate une liste html, ul dans laquelle avec une jolie boucle on ajoute une ligne li qui contient la nom de famille, et le prenom pour chaque proposition.
  • il est tres important d'ajouer le - apres le do et apres le end. sans cela nos propositions ne serait pas selectionnable. Cest à dire que le clic ne marcherait pas.

Nous en avons terminé avec la phase initiale : afficher un champ texte avec l'auto-complete.

5 Une petite methode sympathique, find_by_fullname :

Dans notre controleur on ajoute le methode suivante :

def find_by_fullname(name)
    Person.find(:first, :conditions =>['LOWER(CONCAT(lastname," ",firstname)) = ?',name.downcase ])
end

Elle retourne une liste de personne grace la leur nom de famille + prenom ...

6 eme etape ... le retour (pas de Jedi ...)

quand on soumet notre formulaire de recherche, on arrive sur l'action search suivante :

def search
   @person = find_by_fullname(params[:search][:name])
    if @person
       redirect_to :action => 'show', :id => @person
    else
       flash[:notice] = _('Person not found.')
       redirect_to :action => 'list'
    end
end

nous y voila :

  • on cherche la personne avec son nom et son prenom.
  • si on trouve la personne qui correspond, on redirige sur l'action show avec l'id de la personne.
  • sinon on redirige sur la page liste.

Conclusion :

Comme d'habitude avec Ruby On Rails, il suffit d'un peu de ligne de code et on arrive tres vite a faire quelque chose de vraiment fonctionnel en applicatif web.

Notes

[1] un petit conseil essayez de mettre le champs plutot vers le haute de la page. Parce que s'il est trop bas, quand la liste de propositions s'ouvre, elle modie la taille de la page en hauteur.

[2] pour mieux comprendre dans le detail ajax voir l'exellent article d'openweb ici L'objet XMLHttpRequest.