web-dev-qa-db-fra.com

Afficher les étiquettes des datalistes mais soumettre la valeur réelle

Actuellement, l'élément HTML5 <datalist> Est pris en charge par la plupart des navigateurs principaux (sauf Safari) et semble être un moyen intéressant d'ajouter des suggestions à une entrée.

Cependant, il semble y avoir des divergences entre la mise en œuvre de l'attribut value et le texte interne du <option>. Par exemple:

<input list="answers" name="answer">
<datalist id="answers">
  <option value="42">The answer</option>
</datalist>

Ceci est géré différemment par différents navigateurs:

Chrome et Opera:
Datalist in Chrome/Opera

FireFox et IE 11:
Datalist in FireFox

Après en avoir sélectionné un, l'entrée est remplie avec la valeur et non le texte intérieur. Je veux seulement que l'utilisateur voie le texte ("La réponse") dans le menu déroulant et dans l'entrée, mais passe la valeur 42 À submit, comme le ferait un select.

Comment puis-je faire en sorte que tous les navigateurs aient la liste déroulante affichant les étiquettes (texte interne) du <option>, Mais envoient l'attribut value lorsque le formulaire est soumis?

68
Stephan Muller

Notez que datalist n’est pas identique à un select. Il permet aux utilisateurs de saisir une valeur personnalisée qui ne figure pas dans la liste et il serait impossible d'extraire une autre valeur pour cette entrée sans la définir au préalable.

Les manières possibles de gérer les entrées utilisateur sont de soumettre la valeur entrée telle quelle, de soumettre une valeur vide ou d'empêcher la soumission. Cette réponse ne traite que les deux premières options.

Si vous souhaitez totalement interdire les entrées utilisateur, peut-être que select serait un meilleur choix.


Pour afficher uniquement la valeur textuelle de option dans la liste déroulante, nous utilisons le texte interne pour cela et omettons l'attribut value. La valeur réelle que nous voulons envoyer est stockée dans un fichier personnalisé data-value attribut:

Pour soumettre ce data-value nous devons utiliser un <input type="hidden">. Dans ce cas, nous omettons le name="answer" sur l'entrée normale et déplacez-le vers la copie masquée.

<input list="suggestionList" id="answerInput">
<datalist id="suggestionList">
    <option data-value="42">The answer</option>
</datalist>
<input type="hidden" name="answer" id="answerInput-hidden">

De cette façon, lorsque le texte de l'entrée d'origine change, nous pouvons utiliser javascript pour vérifier si le texte également présent dans datalist et récupérer son data-value. Cette valeur est insérée dans l'entrée masquée et soumise.

document.querySelector('input[list]').addEventListener('input', function(e) {
    var input = e.target,
        list = input.getAttribute('list'),
        options = document.querySelectorAll('#' + list + ' option'),
        hiddenInput = document.getElementById(input.getAttribute('id') + '-hidden'),
        inputValue = input.value;

    hiddenInput.value = inputValue;

    for(var i = 0; i < options.length; i++) {
        var option = options[i];

        if(option.innerText === inputValue) {
            hiddenInput.value = option.getAttribute('data-value');
            break;
        }
    }
});

L'identifiant answer et answer-hidden sur les entrées régulières et cachées sont nécessaires au script pour savoir quelle entrée appartient à quelle version cachée. De cette façon, il est possible d’avoir plusieurs inputs sur la même page avec un ou plusieurs datalists fournissant des suggestions.

Toute entrée d'utilisateur est soumise telle quelle. Pour soumettre une valeur vide lorsque l'entrée utilisateur n'est pas présente dans le datalist, modifiez hiddenInput.value = label à hiddenInput.value = ""


Exemples de travail jsFiddle: javascript simple et jQuery

83
Stephan Muller

La solution que j'utilise est la suivante:

<input list="answers" id="answer">
<datalist id="answers">
  <option data-value="42" value="The answer">
</datalist>

Accédez ensuite à la valeur à envoyer au serveur en utilisant JavaScript comme ceci:

var shownVal = document.getElementById("answer").value;
var value2send = document.querySelector("#answers option[value='"+shownVal+"']").dataset.value;


J'espère que ça aide.

29
Hezbullah Shah

Lorsque vous cliquez sur le bouton de recherche, vous pouvez le trouver sans boucle.
Ajoutez simplement à l'option un attribut avec la valeur dont vous avez besoin (comme id) et recherchez-le de manière spécifique.

$('#search_wrapper button').on('click', function(){
console.log($('option[value="'+ 
$('#autocomplete_input').val() +'"]').data('value'));
})
1
Gal Albalak