L’idée consiste à créer une belle barre de recherche qui alignerait une sélection de catégories, la saisie de mots-clés dans un champ input
et le bouton soumettre tout au bout. La chance est de notre côté, car s’il fut une époque où il fallait coder le tout, il existe d’ailleurs un tas de code plus ou moins concluant sur le web, aujourd’hui il suffit de Bootstrap pour ce faire.
Deux techniques possible, avec l’élément HTML du formulaire « liste de sélection » select
ou encore avec la composante « liste déroulante » dropdowns
de Bootstrap. Il ne manque qu’un petit bout de code JavaScript pour transférer la valeur de la catégorie au formulaire dans ce dernier cas.
Exemple complet avec validation Bootstrap
Barre de recherche avec « liste de sélection » (select)
C’est la méthode la plus simple, la plus intuitive et la plus logique en utilisant un élément déjà disponible, liste de sélection, pour un formulaire. Avec un tout petit ajustement de la feuille de style. Commençons par grouper le tout avec la classe input-group
. La sélection de la classe devant la saisie des mots-clés avec la classe input-group-prepend
et le bouton « soumettre » (submit) après la saisie avec la classe input-group-append
:
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous" /> <div class="container"> <form class="form-inline" action="/recherche/" method="get"> <fieldset> <div class="input-group"> <div class="input-group-prepend"> <select id="oCategorie" name="oCategorie" class="form-control"> <option selected="selected" value="0">Catégorie</option> <option value="1">...</option> </select> </div> <input id="oSaisie" name="oSaisie" type="text" class="form-control" aria-label="Saisie de mots clés" required="required"> <div class="input-group-append"> <button class="btn btn-primary" type="submit">Recherche</button> </div> </div> </fieldset> </form> </div>
Déjà Bootstrap ne suffit visiblement pas. Le formulaire à bien sûr une largeur variable à cause de la classe form-inline
qu’il suffit d’enlever, mais bizarrement et malgré l’usage de la classe Bootstrap form-control
, la flèche de la liste de sélection est celle par défaut du navigateur. De plus, la liste de sélection ne s’intègre pas du tout au groupe, comme s’il n’y avait aucune prise en charge par le groupe de saisie input-group
! Et pourtant, quoi de plus naturel pour un formulaire d’avoir une liste de sélection ! Un oublie de Bootstrap ? Ce formulaire a néanmoins la capacité de fonctionner sans aucun code JavaScript, c’est uniquement la présentation qui jure...
Pour améliorer la présentation, retirer la classe form-inline
et surtout utiliser la classe custom-select
au lieu de form-control
(!). Ça devrait régler le cas de la flèche. Il reste les deux rondeur au bout de la liste à supprimer en utilisant (pourquoi pas) toujours la même classe de Bootstrap inexplicablement nommée custom-select
(!) :
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous" /> <style> .custom-select { border-top-right-radius: 0; border-bottom-right-radius: 0; } </style> <div class="container"> <form action="/recherche/" method="get"> <fieldset> <div class="input-group"> <div class="input-group-prepend"> <select id="oCategorie" name="oCategorie" class="custom-select bg-primary text-light"> <option selected="selected" value="0">Catégorie</option> <option value="1">...</option> </select> </div> <input id="oSaisie" name="oSaisie" type="text" class="form-control" aria-label="Saisie de mots clés" placeholder="Mot(s) clé(s)" required="required"> <div class="input-group-append"> <button class="btn btn-primary" type="submit">Recherche</button> </div> </div> </fieldset> </form> </div>
Voilà qui fait l’affaire, sans aucun code supplémentaire. Noter que dans cet exemple, j’ai essayé de donner la couleur primaire à la liste, comme le bouton. Rien d’exceptionnel, un simple fond bg-primary
mais aussi un texte text-light
et encore, reste la flèche... C’est pour démontrer une fois encore le manque de support de la liste de sélection par Bootstrap lui-même. Alors que l’exemple qui suit avec la « liste déroulante » (dropdowns), qui demande plus de programmation, n’a besoin que d’une simple classe exactement comme le bouton pour la même couleur...
Barre de recherche avec « liste déroulante » (dropdowns)
Ce formulaire est aussi groupé à l’aide de la classe input-group
mais au lieu d’utiliser un élément du formulaire, le formulaire utilise une composante de Bootstrap, la liste déroulante dropdowns
. Ce qui procure plus de flexibilité, par contre ce formulaire ne fonctionne pas seul. En effet, la sélection d’une catégorie n’est pas prise en charge par le formulaire, ce n’est pas un élément du formulaire, c’est normal. C’est-à-dire que non seulement la catégorie n’est pas transmise par le formulaire, mais la sélection ne fonctionne tout simplement pas sans JavaScript ni même sans jQuery ! Pire, la sélection ne modifie même pas l’étiquette ! Comme tous les exemples par Bootstrap de la composante dropdowns
. Ironiquement, la liste déroulante est bien prise en charge cette fois par le groupe input-group
, avec rondeur, couleurs de fond, etc (!)
Le formulaire est donc tout aussi simple et même de base, sans style particulier, mais avec JavaScript.
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous" /> <div class="container"> <form> <fieldset> <input id="oCategorieValeur" name="oCategorieValeur" type="hidden" value="0" /> <div class="input-group"> <div class="input-group-prepend"> <button id="oCategorie" class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Catégorie</button> <div id="oCategorieListe" class="dropdown-menu"> <a class="dropdown-item" data-valeur="0" href="#">Catégorie</a> <a class="dropdown-item" data-valeur="1" href="#">...</a> </div> </div> <input id="oSaisie" name="oSaisie" type="text" class="form-control" aria-label="Saisie de mots clés" placeholder="Mot(s) clé(s)" required="required"> <div class="input-group-append"> <button class="btn btn-primary" type="submit">Recherche</button> </div> </div> </fieldset> </form> </div> <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.bundle.min.js" integrity="sha384-6khuMg9gaYr5AxOqhkVIODVIvm9ynTT5J4V1cfthmT+emCG6yVmEZsRHdxlotUnm" crossorigin="anonymous"></script> <script> $(document).ready(function(e){ // Boucler tous les hyperliens de la liste « oCategorieListe » // Et capturer le l’événement « click » $('#oCategorieListe').find('a').click(function(e) { // Prévenir une action e.preventDefault(); // Changer l’étiquette (label) de la liste pour le contenu du lien $('#oCategorie').html($(this).html()); // Assigner la valeur de l’attribut « data-valeur » à l’élément caché (hidden) du formulaire « oCategorieValeur » $('#oCategorieValeur').val($(this).attr("data-valeur")); }); }); </script>
Après avoir soumis ce dernier formulaire (avec la méthode GET), jeter un œil sur la barre d’adresse, vous devriez voir les paramètres ?oCategorieValeur=[Valeur]&oSaisie=[valeur]
Validation
Même si le navigateur valide déjà automatiquement le formulaire, par exemple les champs obligatoires required
, un formulaire Bootstrap digne de ce nom a son propre système de validation ! Deux étapes, retirer la validation native du navigateur avec novalidate
et ajouter un petit JavaScript pour le valider manuellement à l’aide de la classe avec-validation
. Notez que cette méthode fonctionne en symbiose avec le DOM, mais il faut ajouter un espace pour afficher le message d’erreur automatique. Noter que l’expression régulière (pattern) est pour forcer l’usager à entrer au moins 3 caractères :
<form class="avec-validation" novalidate="novalidate"> <div class="input-group"> ... <input id="oSaisie" name="oSaisie" type="text" class="form-control" placeholder="Mot(s) clé(s)" aria-label="Saisie de mots clés" pattern=".{3,}" required="required"> ... <div class="invalid-feedback">Veuillez entrer au moins 3 caractères.</div> </div> </form> <script> (function() { // Script Bootstrap pour validation manuelle // car le formulaire n'est pas validé (novalidate) 'use strict'; window.addEventListener('load', function() { var forms = document.getElementsByClassName('avec-validation'); var validation = Array.prototype.filter.call(forms, function(form) { // Soumettre form.addEventListener('submit', function(event) { if (form.checkValidity() === false) { // Non valide, arrête l’envoi event.preventDefault(); event.stopPropagation(); } // Classe de Bootstrap valide form.classList.add('was-validated'); }, false); }); }, false); })(); </script>
Voilà, ne reste plus qu’à faire la recherche, mais ça c’est une autre histoire ; -) Voir le résultat avec un peu plus de style Exemple complet avec validation Bootstrap.