Obtenir la valeur de case à cocher dans ASP.NET MVC 4


122

Je travaille sur une application ASP.NET MVC 4. Cette application a une forme de base. Le modèle de mon formulaire ressemble à ceci:

public class MyModel
{
    public string Name { get; set; }
    public bool Remember { get; set; }
}

Dans mon formulaire, j'ai le code HTML suivant.

<input id="Name" name="Name" type="text" value="@Model.Name" />
<input id="Remember" name="Remember" type="checkbox" value="@Model.Remember" />
<label for="Remember">&nbsp;Remember Me?</label>

Lorsque je publie le formulaire, la valeur Remember du modèle est toujours fausse. Cependant, la propriété Name du modèle a une valeur. J'ai testé cela en définissant un point d'arrêt dans ce qui suit:

[HttpPost]
public ActionResult MyAction(MyModel model)
{
  Console.WriteLine(model.Remember.ToString());
}

Je ne peux pas comprendre. Pourquoi la valeur Checkbox n'est-elle pas définie?


Est-il affiché avec la valeur appropriée? Pouvez-vous vérifier cela en utilisant Fiddler? De plus, je ne sais pas si / comment la valeur de la case à cocher se traduit en booléen.
shahkalpesh

Cela est affiché comme «activé» ou «désactivé» dans le formulaire. Cela ne lie apparemment pas correctement. J'ai fait une énumération stupide pour éviter cela.
Yablargo

@Yablargo, vous n'avez pas besoin de l'énumération. Ajoutez simplement value = "true" à la balise d'entrée. Et utilisez un hidden avec value = "false" comme indiqué ci-dessous.
greg sympatrique

Réponses:


213
@Html.EditorFor(x => x.Remember)

Générera:

<input id="Remember" type="checkbox" value="true" name="Remember" />
<input type="hidden" value="false" name="Remember" />

Comment ça marche:

  • Si checkboxreste décochée, le formulaire soumet uniquement la hiddenvaleur (faux)
  • Si coché, le formulaire soumet deux champs (faux et vrai) et des ensembles MVC truepour la boolpropriété du modèle

<input id="Remember" name="Remember" type="checkbox" value="@Model.Remember" />

Cela enverra toujours la valeur par défaut, si elle est cochée.


7
Salut, ce comportement fait échouer les validations de mon modèle car il ne semble pas être en mesure de transformer le [vrai, faux] en une seule valeur booléenne. Comment contourner ce problème?
Obi

@ObiOnuorah Quelle construction utilisez-vous? Aide OU balisage html codé en dur?
webdeveloper

5
Html.EditorFor ou Html.CheckBoxFor donne le même résultat
Obi

3
Si formCollection est utilisé, la chaîne renvoyée pour la case à cocher comme résultat est: "true, false". Comment analysez-vous cela? Replace () est-il la seule option?
Jo Smo le

7
Si vous ajoutez vos propres cases à cocher manuellement, l'élément clé est que la valeur doit être définie sur "true" , sinon la valeur par défaut renvoyée par le formulaire sera "on" et "on" ne peut pas être lié à un booléen qui a besoin de vrai / faux. (Vous pouvez voir une erreur de validation indiquant que la valeur "on" n'est pas valide pour le champ .)
Greg

69

Puisque vous utilisez Model.Name pour définir la valeur. Je suppose que vous transmettez un modèle de vue vide à la vue.

La valeur de Remember est donc false et définit la valeur de l'élément checkbox sur false. Cela signifie que lorsque vous cochez ensuite la case, vous publiez la valeur «false» avec le formulaire. Lorsque vous ne le sélectionnez pas, il n'est pas publié, donc le modèle par défaut est false. C'est pourquoi vous voyez une fausse valeur dans les deux cas.

La valeur n'est transmise que lorsque vous cochez la case de sélection. Pour faire une case à cocher dans Mvc, utilisez

@Html.CheckBoxFor(x => x.Remember)

ou si vous ne souhaitez pas lier le modèle à la vue.

@Html.CheckBox("Remember")

Mvc fait de la magie avec un champ caché pour conserver les valeurs lorsqu'elles ne sont pas sélectionnées.

Edit, si vous avez vraiment une aversion pour faire cela et que vous voulez générer l'élément vous-même, vous pouvez le faire.

<input id="Remember" name="Remember" type="checkbox" value="true" @(Model.Remember ? "checked=\"checked\"" : "") />

2
Le @Html.CheckboxForcode devrait en fait être@Html.CheckBoxFor
fujiiface

Juste un rapide, comment utiliseriez-vous @(Model.Remember ? "checked=\"checked\"" : "")sur un bouton radio? ou est-ce pas possible
Izzy

Avec cette option, vous manipulez simplement le HTML directement, un bouton radio est juste type="radio", et la sélection de celle que vous voulez sélectionner dans le HTML est la même que ci-dessus checked="checked",. La différence étant que vous aurez plusieurs <input />éléments avec le même nom. Vous devez déterminer à laquelle appliquer le HTML supplémentaire.
Dan Saltmer

@Html.CheckBoxFor(x => x.Remember)cela a fonctionné pour moi
JustLearning

15

Utilisez uniquement ceci

$("input[type=checkbox]").change(function () {
    if ($(this).prop("checked")) {
        $(this).val(true);
    } else {
        $(this).val(false);
    }
});

Ou:$(this).val($(this).is(":checked"));
Norman le

5

Au lieu de

 <input id="Remember" name="Remember" type="checkbox" value="@Model.Remember" />

utilisation:

 @Html.EditorFor(x => x.Remember)

Cela vous donnera une case à cocher spécifiquement pour Remember


4

D'accord, la case à cocher est un peu bizarre. Lorsque vous utilisez l'aide Html, il génère deux entrées de case à cocher sur le balisage, et les deux sont transmises en tant que paire nom-valeur de IEnumerable si elle est cochée.

S'il n'est pas vérifié sur le balisage, il n'est transmis que dans l'entrée masquée qui a la valeur false.

Donc, par exemple sur le balisage que vous avez:

      @Html.CheckBox("Chbxs") 

Et dans l'action du contrôleur (assurez-vous que le nom correspond au nom du paramètre de la case à cocher sur le contrôleur):

      public ActionResult Index(string param1, string param2,
      string param3, IEnumerable<bool> Chbxs)

Ensuite, dans le contrôleur, vous pouvez faire des choses comme:

      if (Chbxs != null && Chbxs.Count() == 2)
        {
            checkBoxOnMarkup = true;
        }
        else
        {
            checkBoxOnMarkup = false;
        }

Je sais que ce n’est pas une solution élégante. J'espère que quelqu'un ici pourra vous donner des conseils.


3

Pour convertir une valeur renvoyée par une case à cocher dans un formulaire en une propriété booléenne, j'ai utilisé le convertisseur de construction ValueProviderResult dans un ModelBinder personnalisé.

ValueProviderResult cbValue = bindingContext.ValueProvider.GetValue("CheckBoxName");
bool value = (bool)cbValue.ConvertTo(typeof(bool));

3

Si vous travaillez avec FormCollection plutôt qu'avec model, l'affectation peut être aussi simple que:

MyModel.Remember = fields["Remember"] != "false";

2

J'ai rencontré un problème similaire et j'ai pu récupérer la valeur de la case à cocher en utilisant une case à cocher, hiddenfor et un petit JQuery comme ceci:

@Html.CheckBox("isPreferred", Model.IsPreferred)
@Html.HiddenFor(m => m.IsPreferred)

<script>

    $("#isPreferred").change(function () {

        $("#IsPreferred").val($("#isPreferred").val());

    })

</script>

2

Cela a été une douleur majeure et semble que cela devrait être plus simple. Voici ma configuration et ma solution.

J'utilise l'aide HTML suivante:

@Html.CheckBoxFor(model => model.ActiveFlag)

Ensuite, dans le contrôleur, je vérifie la collecte du formulaire et je traite en conséquence:

bool activeFlag = collection["ActiveFlag"] == "false" ? false : true;
[modelObject].ActiveFlag = activeFlag;

D'accord, j'ai rendu cela encore plus court car user.IsActive = fc["IsActive"] != "false";je me sens toujours sale d'avoir fait une comparaison de cordes dessus.
WildJoe

1

Je viens de tomber dessus (je ne peux pas croire que ça ne se lie pas!)

Bref!

<input type="checkbox" name="checked" />

Publiera une valeur «on» ou «off».

Cela ne se liera pas à un booléen, mais vous pouvez faire cette solution de contournement stupide!

 public class MyViewModel
 {
     /// <summary>
     /// This is a really dumb hack, because the form post sends "on" / "off"
     /// </summary>                    
     public enum Checkbox
     {
        on = 1,
        off = 0
     }
     public string Name { get; set; }
     public Checkbox Checked { get; set; }
}

1
@Html.EditorFor(x => x.ShowComment)


$(function () {
        // set default value to control on document ready instead of 'on'/'off' 
        $("input[type='checkbox'][name='ShowComment']").val(@Model.ShowComment.ToString().ToLower());
    });

    $("#ShowComment").change(function() {
        // this block sets value to checkbox control for "true" / "false"

        var chkVal = $("input[type='checkbox'][name='ShowComment']").val();
        if (chkVal == 'false') $("input[type='checkbox'][name='ShowComment']").val(true);
        else $("input[type='checkbox'][name='ShowComment']").val(false);

    });

3
Bonjour Surendran et bienvenue dans Stack Overflow. Lorsque vous incluez du code, veuillez le formater pour plus de lisibilité. Mais plus important encore, il est crucial d'expliquer pourquoi le code inclus répond à la question du PO.
Alex A.

1

Pour le MVC utilisant Model. Modèle:

public class UserInfo
{
    public string UserID { get; set; }
    public string UserName { get; set; }
    public string Password { get; set; }
    public bool RememberMe { get; set; }
}

HTML:

<input type="checkbox" value="true" id="checkbox1" name="RememberMe" checked="@Model.RememberMe"/>
<label for="checkbox1"></label>

Dans la fonction [HttpPost], nous pouvons obtenir ses propriétés.

[HttpPost]
public ActionResult Login(UserInfo user)
{
   //...
   return View(user);
}

1

Si vous voulez vraiment utiliser du HTML brut (pour une raison quelconque) et non les extensions HtmlHelper intégrées, vous pouvez le faire de cette façon.

Au lieu de

<input id="Remember" name="Remember" type="checkbox" value="@Model.Remember" />

essayez d'utiliser

<input id="Remember" name="Remember" type="checkbox" value="true" @(Model.Remember ? "checked" : "") />

Les entrées de case à cocher dans HTML fonctionnent de sorte que lorsqu'elles sont cochées, elles envoient la valeur, et lorsqu'elles ne sont pas cochées, elles n'envoient rien du tout (ce qui entraînera le retour d'ASP.NET MVC à la valeur par défaut du champ, false). En outre, la valeur de la case à cocher en HTML peut être autre chose que true / false, donc si vous le souhaitez vraiment, vous pouvez même utiliser une case à cocher pour un champ de chaîne dans votre modèle.

Si vous utilisez la fonction intégrée Html.RenderCheckbox, elle génère en fait deux entrées: une case à cocher et un champ masqué afin qu'une fausse valeur soit envoyée lorsque la case est décochée (pas simplement rien). Cela peut provoquer des situations inattendues, comme celle-ci:


0

Pour plusieurs cases à cocher avec le même nom ... Code pour supprimer les faux inutiles:

List<string> d_taxe1 = new List<string>(Request.Form.GetValues("taxe1"));
d_taxe1 = form_checkbox.RemoveExtraFalseFromCheckbox(d_taxe1);

Fonction

public class form_checkbox
{

    public static List<string> RemoveExtraFalseFromCheckbox(List<string> val)
    {
        List<string> d_taxe1_list = new List<string>(val);

        int y = 0;

        foreach (string cbox in val)
        {

            if (val[y] == "false")
            {
                if (y > 0)
                {
                    if (val[y - 1] == "true")
                    {
                        d_taxe1_list[y] = "remove";
                    }
                }

            }

            y++;
        }

        val = new List<string>(d_taxe1_list);

        foreach (var del in d_taxe1_list)
            if (del == "remove") val.Remove(del);

        return val;

    }      



}

Utilise le :

int x = 0;
foreach (var detail in d_prix){
factured.taxe1 = (d_taxe1[x] == "true") ? true : false;
x++;
}

0
public ActionResult Index(string username, string password, string rememberMe)
{
   if (!string.IsNullOrEmpty(username))
   {
      bool remember = bool.Parse(rememberMe);
      //...
   }
   return View();
}

0

Modifier Souvenez-vous comme ça

public class MyModel
{
    public string Name { get; set; }
    public bool? Remember { get; set; }
}

Utilisez un bool nullable dans le contrôleur et utilisez la valeur false sur null comme ceci

[HttpPost]
public ActionResult MyAction(MyModel model)
{
    model.Remember = model.Remember ?? false;
    Console.WriteLine(model.Remember.ToString());
}

0

Dans mon cas, je ne définissais pas la propriété de modèle "Remember" dans la méthode get. Vérifiez votre logique dans le contrôleur. Vous faites peut-être la même chose. J'espère que cette aide!


0

J'ai lu les autres réponses et je ne l'ai pas tout à fait fonctionné - voici donc la solution avec laquelle j'ai abouti.

Mon formulaire utilise le Html.EditorFor(e => e.Property)pour générer la case à cocher, et en utilisant FormCollectiondans le contrôleur, cela transmet une valeur de chaîne de 'true,false'dans le contrôleur.

Lorsque je gère les résultats, j'utilise une boucle pour les parcourir - j'utilise également une InfoPropertyinstance pour représenter la valeur actuelle du modèle évaluée à partir du formulaire.

Donc, à la place, je vérifie simplement si la chaîne retournée commence par le mot 'true', puis je définis une variable booléenne trueet la transmet au modèle de retour.

if (KeyName.EndsWith("OnOff"))
{
    // set on/off flags value to the model instance
    bool keyTrueFalse = false;
    if(values[KeyName].StartsWith("true"))
    {
        keyTrueFalse = true;
    }
    infoProperty.SetValue(processedInfo, keyTrueFalse);
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.