Comment s'assurer qu'un champ de formulaire <select> est soumis lorsqu'il est désactivé?

180

J'ai un selectchamp de formulaire que je veux marquer comme "lecture seule", car l'utilisateur ne peut pas modifier la valeur, mais la valeur est toujours soumise avec le formulaire. L'utilisation de l' disabledattribut empêche l'utilisateur de modifier la valeur, mais ne soumet pas la valeur avec le formulaire.

L' readonlyattribut n'est disponible que pour les champs inputet textarea, mais c'est essentiellement ce que je veux. Y a-t-il un moyen de faire fonctionner cela?

Deux possibilités que j'envisage incluent:

  • Au lieu de désactiver le select, désactivez tous les options et utilisez CSS pour griser la sélection afin qu'elle semble désactivée.
  • Ajoutez un gestionnaire d'événements de clic au bouton d'envoi afin qu'il active tous les menus déroulants désactivés avant de soumettre le formulaire.
Marquis Wang
la source
2
désolé d'être trafalmadorianarrivé tard, mais les solutions fournies par @ workest sont les meilleures. Il désactive toutes les entrées non sélectionnées. Cela fonctionnerait également si plusieurs options sont activées. $('#toSelect')find(':not(:selected)').prop('disabled',true);
Abhishek Madhani
Sinon, vous pouvez laisser le contrôle désactivé sur l'interface utilisateur, mais récupérer la valeur dans la méthode d'action: public ActionResult InsertRecord (modèle MyType) {if (model.MyProperty == null) {model.MyProperty = Request ["MyProperty"]; }}
beastieboy

Réponses:

118
<select disabled="disabled">
    ....
</select>
<input type="hidden" name="select_name" value="selected value" />

select_nameest le nom que vous donneriez normalement au fichier <select>.

Une autre option.

<select name="myselect" disabled="disabled">
    <option value="myselectedvalue" selected="selected">My Value</option>
    ....
</select>
<input type="hidden" name="myselect" value="myselectedvalue" />

Maintenant, avec celui-ci, j'ai remarqué que selon le serveur Web que vous utilisez, vous devrez peut-être mettre l' hiddenentrée avant ou après le <select>.

Si ma mémoire me sert correctement, avec IIS, vous le mettez avant, avec Apache vous le mettez après. Comme toujours, les tests sont essentiels.

Jordan S. Jones
la source
3
Comment cela dépendrait-il du serveur Web ? N'est-ce pas le client qui rend la page avec le champ de sélection, et donc en cas de conflit comme celui-là, ce serait le client qui déciderait d'envoyer la valeur au serveur ou non?
Ilari Kajaste
8
Cela dépend de la façon dont le serveur gère plusieurs entrées avec le même nom.
Jordan
1
Vous feriez mieux de ne pas vous fier à un type de serveur spécifique, donc je pense que la première approche est plus propre et moins sujette aux erreurs.
Luc
5
@Jordan: les navigateurs n'envoient pas les valeurs des champs désactivés au serveur, c'est pourquoi ils sont vides lorsque vous essayez de les gérer côté serveur. Si vous avez un champ masqué avec la valeur souhaitée et que le ou les champs visibles sont désactivés, seul le champ masqué sera envoyé au serveur. Ergo, le champ caché ne doit être créé (via JS ou code côté serveur) que lorsque les champs visibles sont désactivés et qu'il n'y a pas de problème de priorité.
Matt van Andel
1
Ce n'est une option que si vous avez besoin d'un formulaire qui fonctionne sans javascript.
Andrew
224

Désactivez les champs, puis activez-les avant l'envoi du formulaire:

Code jQuery:

jQuery(function ($) {        
  $('form').bind('submit', function () {
    $(this).find(':input').prop('disabled', false);
  });
});
Tres
la source
15
Une bonne solution!
Chris
2
C'est celui sur lequel je me suis arrêté, principalement parce que c'est le moins intrusif.
Jonathan
3
Les documents jQuery recommandent d'utiliser .prop et .removeProp pour 'vérifié', 'sélectionné' et 'désactivé' au lieu de .attr et .removeAttr voir http://api.jquery.com/prop/
Jim Bergman
2
Bit pertinent du commentaire de @ JimBergman - "Les propriétés affectent généralement l'état dynamique d'un élément DOM sans changer l'attribut HTML sérialisé. Les exemples incluent la propriété value des éléments d'entrée, la propriété désactivée des entrées et des boutons ou la propriété cochée d'une case à cocher. La méthode .prop () doit être utilisée pour définir désactivé et vérifié au lieu de la méthode .attr (). La méthode .val () doit être utilisée pour obtenir et définir la valeur. " - de api.jquery.com/prop
Joshua Dance
2
You are genius one (Y)
TommyDo
13

J'ai cherché une solution pour cela, et comme je n'ai pas trouvé de solution dans ce fil, j'ai fait la mienne.

// With jQuery
$('#selectbox').focus(function(e) {
    $(this).blur();
});

Simple, vous floutez simplement le champ lorsque vous vous concentrez dessus, quelque chose comme le désactiver, mais vous envoyez en fait ses données.

Jean Paul Rumeau
la source
Wow Solution géniale et facile. Merci .. +1 de moi :)
Naeem Ul Wahhab
J'aime beaucoup ça ... en fonction des interactions dans mon formulaire, les éléments deviennent activés / désactivés d'avant en arrière ... comment réactiver un champ «flou» dans ce scénario?
bkwdesign
Sur Google, ressemble à $ ('# selectbox'). Off ('focus'); ferait le tour de la réactivation
bkwdesign
2
fonctionne pour les zones de texte, ne fonctionne pas pour les zones de sélection, plus facile à déplacer en cliquant et en maintenant le bouton enfoncé
Andrew
7

J'ai été confronté à un scénario légèrement différent, en ce sens que je voulais seulement ne pas permettre à l'utilisateur de modifier la valeur sélectionnée en fonction d'une boîte de sélection antérieure. Ce que j'ai fini par faire, c'est simplement désactiver toutes les autres options non sélectionnées dans la boîte de sélection en utilisant

$('#toSelect')find(':not(:selected)').attr('disabled','disabled');
trafalmadorien
la source
Merci, j'ai trouvé le vôtre le plus simple du point de vue logique. Cependant attrdevrait changer avec prop, ressemblerait à quelque chose comme$('#toSelect')find(':not(:selected)').prop('disabled',true);
Abhishek Madhani
6

Même solution suggérée par Tres sans utiliser jQuery

<form onsubmit="document.getElementById('mysel').disabled = false;" action="..." method="GET">

   <select id="mysel" disabled="disabled">....</select>

   <input name="submit" id="submit" type="submit" value="SEND FORM">
</form>

Cela peut aider quelqu'un à mieux comprendre, mais est évidemment moins flexible que celui de jQuery.

Marco Demaio
la source
Mais ce n'est pas bien pour plusieurs sélecteurs. Peut-être pouvons-nous utiliser getElementsByTagName('select')?
Chanceux
6

il ne fonctionne pas avec le: sélecteur d'entrée pour les champs sélectionnés, utilisez ceci:

    jQuery(function() {

    jQuery('form').bind('submit', function() {
        jQuery(this).find(':disabled').removeAttr('disabled');
    });

    });
chhalpha
la source
5

J'utilise le code suivant pour désactiver les options dans les sélections

<select class="sel big" id="form_code" name="code" readonly="readonly">
   <option value="user_played_game" selected="true">1 Game</option>
   <option value="coins" disabled="">2 Object</option>
   <option value="event" disabled="">3 Object</option>
   <option value="level" disabled="">4 Object</option>
   <option value="game" disabled="">5 Object</option>
</select>

// Disable selection for options
$('select option:not(:selected)').each(function(){
 $(this).attr('disabled', 'disabled');
});
Aleks
la source
4

Le moyen le plus simple que j'ai trouvé était de créer une minuscule fonction javascript liée à votre formulaire:

function enablePath() {
    document.getElementById('select_name').disabled= "";
}

et vous l'appelez dans votre formulaire ici:

<form action="act.php" method="POST" name="form_name" onSubmit="enablePath();">

Ou vous pouvez l'appeler dans la fonction que vous utilisez pour vérifier votre formulaire :)

Alex PARISOT
la source
4

Ajoutez simplement une ligne avant de soumettre.

$ ("# XYZ"). RemoveAttr ("désactivé");

PPB
la source
2

Ou utilisez du JavaScript pour changer le nom de la sélection et la désactiver. De cette façon, la sélection est toujours soumise, mais en utilisant un nom que vous ne vérifiez pas.

Byron Whitlock
la source
2

J'ai créé un plugin rapide (Jquery uniquement), qui enregistre la valeur dans un champ de données lorsqu'une entrée est désactivée. Cela signifie simplement que tant que le champ est désactivé par programmation via jquery en utilisant .prop () ou .attr () ... alors accéder à la valeur par .val (), .serialize () ou .serializeArra () retournera toujours le valeur même si désactivé :)

Prise sans vergogne: https://github.com/Jezternz/jq-disabled-inputs

Josh Mc
la source
2

Sur la base de la solution de la Jordanie, j'ai créé une fonction qui crée automatiquement une entrée masquée avec le même nom et la même valeur de la sélection que vous souhaitez invalider. Le premier paramètre peut être un id ou un élément jquery; le second est un paramètre optionnel booléen où "true" désactive et "false" active l'entrée. S'il est omis, le deuxième paramètre commute la sélection entre «activé» et «désactivé».

function changeSelectUserManipulation(obj, disable){
    var $obj = ( typeof obj === 'string' )? $('#'+obj) : obj;
    disable = disable? !!disable : !$obj.is(':disabled');

    if(disable){
        $obj.prop('disabled', true)
            .after("<input type='hidden' id='select_user_manipulation_hidden_"+$obj.attr('id')+"' name='"+$obj.attr('name')+"' value='"+$obj.val()+"'>");
    }else{
        $obj.prop('disabled', false)
            .next("#select_user_manipulation_hidden_"+$obj.attr('id')).remove();
    }
}

changeSelectUserManipulation("select_id");
Doglas
la source
le paramètre 'obj' doit être un objet jquery
Doglas
1

J'ai trouvé une solution viable: supprimez tous les éléments sauf celui sélectionné. Vous pouvez ensuite changer le style en quelque chose qui semble également désactivé. Utilisation de jQuery:

jQuery(function($) {
    $('form').submit(function(){
        $('select option:not(:selected)', this).remove();
    });
});
Alftheo
la source
0
<select id="example">
    <option value="">please select</option>
    <option value="0" >one</option>
    <option value="1">two</option>
</select>



if (condition){
    //you can't select
    $("#example").find("option").css("display","none");
}else{
   //you can select
   $("#example").find("option").css("display","block");
}
Thxopen
la source
-8

Une autre option consiste à utiliser l'attribut readonly.

<select readonly="readonly">
    ....
</select>

En lecture seule, la valeur est toujours soumise, le champ de saisie est grisé et l'utilisateur ne peut pas le modifier.

Éditer:

Extrait de http://www.w3.org/TR/html401/interact/forms.html#adef-readonly :

  • Les éléments en lecture seule reçoivent le focus mais ne peuvent pas être modifiés par l'utilisateur.
  • Les éléments en lecture seule sont inclus dans la navigation par tabulation.
  • Les éléments en lecture seule peuvent réussir.

Quand il dit que l'élément peut réussir, cela signifie qu'il peut être soumis, comme indiqué ici: http://www.w3.org/TR/html401/interact/forms.html#successful-controls

Phillip Whelan
la source
6
Le contrôle n'est PAS grisé et l'utilisateur PEUT le modifier. Vous n'avez pas lu toute la section et je cite: "Les éléments suivants prennent en charge l'attribut en lecture seule: INPUT et TEXTAREA."
Carlos Rendon
3
Je sais que c'est une vieille réponse, mais cela fonctionne réellement. Je ne connais pas la raison de nombreux votes négatifs.
Ze Luis