Formulaire de sélection HTML avec option pour saisir une valeur personnalisée

104

Je voudrais avoir un champ de saisie dans lequel les utilisateurs peuvent entrer une valeur de texte personnalisée ou choisir dans la liste déroulante. Un régulier <select>ne propose que des options déroulantes.

Comment puis-je <select>accepter une valeur personnalisée? Par exemple: Ford?

<select>
  <option value="volvo">Volvo</option>
  <option value="saab">Saab</option>
  <option value="mercedes">Mercedes</option>
  <option value="audi">Audi</option>
</select>
Ib33X
la source
Vous pouvez utiliser javascript pour ajouter dynamiquement une option à la sélection, mais l'utilisation de ces informations deviendrait alors une véritable douleur.
David
Je n'ai pas ajouté cette option pour les valeurs personnalisées sur mon site Web finnmglas.com/contact, mais quelqu'un m'a contacté avec une valeur personnalisée. C'est tellement bizarre
finnmglas

Réponses:

249

HTML5 a une zone de liste déroulante intégrée. Vous créez un texte inputet un fichier datalist. Ensuite, vous ajoutez un listattribut à la input, avec une valeur idde la datalist.

Mise à jour: depuis mars 2019, tous les principaux navigateurs (y compris maintenant Safari 12.1 et iOS Safari 12.3) prennent datalisten charge le niveau requis pour cette fonctionnalité. Voir caniuse pour une assistance détaillée du navigateur.

Cela ressemble à ceci:

<input type="text" list="cars" />
<datalist id="cars">
  <option>Volvo</option>
  <option>Saab</option>
  <option>Mercedes</option>
  <option>Audi</option>
</datalist>

Dmitry
la source
3
Cette fonctionnalité n'est prise en charge que par environ 50% des navigateurs. Seuls les derniers Firefox, Chrome et Opera supportent cela; Les navigateurs IE, Safari et mobiles ne le font pas. Voir http://caniuse.com/
markmarijnissen
2
Nous sommes à la moitié de 2016 (plus de 2 ans plus tard) et la plupart des navigateurs ne le prennent toujours pas entièrement en charge, du moins sans bogues importants. Au moins quelque chose fonctionnera sur les versions récentes de presque tout, sauf Safari / Safari iOS, mais vous devez tester pour vous assurer que vos cas d'utilisation fonctionnent correctement. C'est toujours la meilleure réponse.
Michael Gaskill
1
Cela fonctionne bien pour moi. Dans de nombreux cas, nous n'avons pas besoin de prendre en charge les anciens navigateurs. J'ai seulement ajouté l'image "flèche vers le bas" sur l'arrière-plan du champ de saisie pour donner aux utilisateurs un indice qu'il est extensible. Code (vous avez besoin d'un fichier image réel):<input type="text" list="cars" style="background:url('images/arrow_down.png') no-repeat right center">
Eugene Kardash
4
Je viens de tester dans les versions récentes d'IE, Firefox et Chrome avec tout fonctionne bien. Je pense que c'est une excellente solution simple à ce problème commun dans de nombreux cas.
kerl
3
Je voulais vraiment l'utiliser mais j'avais besoin de définir une valeur par défaut. L'utilisateur ne voit que la valeur par défaut dans la liste déroulante par rapport à toutes les options (car elles sont filtrées). Ils auraient besoin de savoir effacer le champ de saisie avant de voir toutes les options.
Justin
26

Le dernier JSFiddle d'Alen Saqe n'a pas basculé pour moi sur Firefox, alors j'ai pensé que je fournirais une solution de contournement simple html / javascript qui fonctionnera bien dans les formulaires (en ce qui concerne la soumission) jusqu'au jour où la balise datalist est acceptée par tous les navigateurs / appareils. Pour plus de détails et le voir en action, rendez-vous sur: http://jsfiddle.net/6nq7w/4/ Remarque: n'autorisez aucun espace entre les frères et sœurs!

<!DOCTYPE html>
<html>
<script>
function toggleField(hideObj,showObj){
  hideObj.disabled=true;        
  hideObj.style.display='none';
  showObj.disabled=false;   
  showObj.style.display='inline';
  showObj.focus();
}
</script>
<body>
<form name="BrowserSurvey" action="#">
Browser: <select name="browser" 
          onchange="if(this.options[this.selectedIndex].value=='customOption'){
              toggleField(this,this.nextSibling);
              this.selectedIndex='0';
          }">
            <option></option>
            <option value="customOption">[type a custom value]</option>
            <option>Chrome</option>
            <option>Firefox</option>
            <option>Internet Explorer</option>
            <option>Opera</option>
            <option>Safari</option>
        </select><input name="browser" style="display:none;" disabled="disabled" 
            onblur="if(this.value==''){toggleField(this,this.previousSibling);}">
<input type="submit" value="Submit">
</form>
</body>
</html>

Mickmackusa
la source
Je voudrais refaire cette histoire! La version sorcière de Firefox n'y était pas prise en charge! Je l'ai testé avec une version dont je ne me souviens plus! Gloire!
Alen Saqe
Je ne sais pas sur quelle version de FF j'étais. Je viens de jeter un oeil sur FF34.0 et je reçois des fonctionnalités maintenant, donc pas de soucis. Cependant, l'option de basculement par défaut «Autre» peut être effacée. Lorsque je supprime «Autre» en modifiant la valeur, le menu déroulant n'offre pas de valeur intuitive à sélectionner (pour accéder à la fonction d'édition). Je pense que cela revient à une préférence personnelle. Étant donné que la flèche du menu déroulant est toujours présente lorsque le champ est modifiable, les utilisateurs peuvent ne pas réaliser que le champ est modifiable. Ne pas avoir une fouille chez vous; juste quelques commentaires. Mon extrait de code considère également la dénomination des champs à l'intérieur d'un <form>.
mickmackusa
Le résultat final de ce script ingénieux mais indéchiffrable (pour moi) + html est d'attacher la valeur d'option sélectionnée, ou le texte saisi, à un GET de la même page en tant que chaîne de requête. Est-ce que quelqu'un sait comment convertir l'action en POST, afin que je puisse saisir la valeur dans un fichier php et y faire quelque chose?
Han
J'ai composé ce script avec l'intention spécifique pour qu'il se comporte conformément aux soumissions de formulaire html. Utilisez-vous la méthode post comme attribut dans la balise form? @Han si vous créez un lien 3v4l.org de votre extrait isolé, je peux jeter un coup d'œil rapide et éventuellement vous conseiller.
mickmackusa le
1
Garçon je me sens stupide. J'ai oublié de mettre une méthode dans la balise form. Cela a fonctionné comme indiqué avec cette très légère modification: <form name = "BrowserSurvey" method = "post" action = "/ gotThis.php"> ... Beau script, mickmackusa. Merci pour votre indice de suivi!
Han
16

Solution jQuery!

Démo: http://jsfiddle.net/69wP6/2/

Une autre démo ci-dessous (mise à jour!)

J'avais besoin de quelque chose de similaire dans un cas où j'avais des options fixes et je voulais qu'une autre option soit modifiable! Dans ce cas, j'ai créé une entrée masquée qui chevaucherait l'option de sélection et serait modifiable et utilisait jQuery pour que tout fonctionne de manière transparente.

Je partage le violon avec vous tous!

HTML

<div id="billdesc">
    <select id="test">
      <option class="non" value="option1">Option1</option>
      <option class="non" value="option2">Option2</option>
      <option class="editable" value="other">Other</option>
    </select>
    <input class="editOption" style="display:none;"></input>
</div>

CSS

body{
    background: blue;
}
#billdesc{
    padding-top: 50px;
}
#test{
    width: 100%;
    height: 30px;
}
option {
    height: 30px;
    line-height: 30px;
}

.editOption{
    width: 90%;
    height: 24px;
    position: relative;
    top: -30px

}

jQuery

var initialText = $('.editable').val();
$('.editOption').val(initialText);

$('#test').change(function(){
var selected = $('option:selected', this).attr('class');
var optionText = $('.editable').text();

if(selected == "editable"){
  $('.editOption').show();


  $('.editOption').keyup(function(){
      var editText = $('.editOption').val();
      $('.editable').val(editText);
      $('.editable').html(editText);
  });

}else{
  $('.editOption').hide();
}
});

Edit: Ajout de quelques touches simples au niveau de la conception, afin que les gens puissent voir clairement où se termine l'entrée!

JS Fiddle: http://jsfiddle.net/69wP6/4/

Alen Saqe
la source
11

Vous ne pouvez pas vraiment. Vous devrez avoir à la fois la liste déroulante et la zone de texte, et leur demander de choisir ou de remplir le formulaire. Sans javascript, vous pouvez créer un ensemble de boutons radio séparés où ils choisissent la liste déroulante ou la saisie de texte, mais cela me semble compliqué. Avec certains javascript, vous pouvez activer ou désactiver l'un ou l'autre en fonction de celui qu'ils choisissent, par exemple, avoir une option «autre» dans la liste déroulante qui déclenche le champ de texte.

Sam
la source
9

Si l'option datalist ne répond pas à vos exigences, jetez un œil à la bibliothèque Select2 et à la " création d'options dynamiques "

$(".js-example-tags").select2({
  tags: true
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/css/select2.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/js/select2.min.js"></script>


<select class="form-control js-example-tags">
  <option selected="selected">orange</option>
  <option>white</option>
  <option>purple</option>
</select>

Sogeking
la source
0

En utilisant l'une des solutions ci-dessus (@mickmackusa), j'ai créé un prototype fonctionnel dans React 16.8+ à l'aide de Hooks.

https://codesandbox.io/s/heuristic-dewdney-0h2y2

J'espère que cela aide quelqu'un.

Dano
la source
Je suis honoré. Je viens de vérifier mes enregistrements et c'était le 12e message que j'ai publié ici sur Stack Overflow - il y a un million d'années.
mickmackusa le
Je viens de jouer avec votre lien de démonstration et il semble que vous ayez perdu l'effet de basculer indéfiniment entre les deux types de champs.
mickmackusa le