web-dev-qa-db-fra.com

Comment implémenter une liste de cases à cocher dans ASP.NET Core?

Je cherche à implémenter une liste de contrôle dans ASP.NET Core, mais je suis confronté à des difficultés. 

Mon ViewModel:

public class GroupIndexViewModel
{
    public Filter[] Filters { get; set; }
}

public class Filter
{
    public int Id { get; set; }
    public string Name { get; set; }
    public bool Selected { get; set; }
}

Mon avis:

@model GroupIndexViewModel
<form asp-action="Index" asp-controller="Group" method="get">
  <ul>
  @for (var i = 0; i < Model.Filters.Length; i++)
  {
    <li>
      <input type="checkbox" id="@Model.Filters[i].Name" asp-for="@Model.Filters[i].Selected" value="@Model.Filters[i].Selected" checked="@Model.Filters[i].Selected" />
      <label for="@Model.Filters[i].Name">@Model.Filters[i].Name</label>
    </li>
  }
  </ul>
  <button type="submit" name="action">Filtrer</button>
</form>

Lors de la publication sur mon contrôleur, la propriété Filter de mon modèle de vue affiche false sélectionnée même si elle est sélectionnée dans la vue.

15
Arnstein

Je referais le chemin suivant. 

@model GroupIndexViewModel
<form asp-action="Index" asp-controller="Group" method="get">
    <ul>
        @for (var i = 0; i < Model.Filters.Count; i++)
        {
            <li>       
                <input type="checkbox" asp-for="@Model.Filters[i].Selected"  />
                <label asp-for="@Model.Filters[i].Selected">@Model.Filters[i].Name</label>
                <input type="hidden" asp-for="@Model.Filters[i].Id" />
                <input type="hidden" asp-for="@Model.Filters[i].Name" />                
            </li>
        }
    </ul>
    <button type="submit" name="action">Filtrer</button>
</form>

Ici, je suppose que vous avez une implémentation correcte du contrôleur et de l’action.

20
dotnetstep

Vous avez peut-être déjà répondu à la question, mais je voulais expliquer votre problème afin que les autres comprennent ce qui se passe.

Vous ne savez pas que vous spécifiez déjà la valeur false à votre entrée, car vous implémentez une mauvaise utilisation des attributs.

_ {Jetons un coup d'oeil à ta vue} _

@model GroupIndexViewModel
<form asp-action="Index" asp-controller="Group" method="get">
   <ul>
     @for (var i = 0; i < Model.Filters.Length; i++)
     {
      <li>
        <input type="checkbox" id="@Model.Filters[i].Name" asp-for="@Model.Filters[i].Selected" value="@Model.Filters[i].Selected" checked="@Model.Filters[i].Selected" />
        <label for="@Model.Filters[i].Name">@Model.Filters[i].Name</label>
     </li>
     }
  </ul>
  <button type="submit" name="action">Filtrer</button>
</form>

Alors, d'abord. Vous créez des éléments d'entrée à partir d'un tableau de Filter. Examinons maintenant de plus près votre élément d’entrée.

<input type="checkbox" id="@Model.Filters[i].Name" asp-for="@Model.Filters[i].Selected" value="@Model.Filters[i].Selected" checked="@Model.Filters[i].Selected" />

Maintenant, laissez-moi expliquer cela.

  1. Vous spécifiez un type à l'aide de l'attribut type.
  2. Vous spécifiez un identifiant à l'aide de l'attribut id.
  3. Vous liez l’entrée au modèle à l’aide de l’assistant de balise asp-for.
  4. Vous spécifiez une valeur pour l'entrée à l'aide de l'attribut value.
  5. Enfin, vous définissez l'entrée comme étant cochée, avec l'attribut checked.

Si vous examinez le Tag Helpers Documentation , vous découvrirez la relation entre Type. Net et Type d'entrée, en comprenant que:

Les cases à cocher contiennent une valeur booléenne correspondant au modèle et formatée par l'assistant de balise en tant que type="checkbox".

Puisque vous utilisez l'attribut type="checkbox", la valeur Tag Helper ne peut être que true ou false. Donc, si nous revenons en arrière et examinons l'élément input, vous spécifiez déjà une valeur pour l'entrée. Même si le tag-helper peut affecter une valeur à l'entrée, il ne peut pas remplacer celle déjà spécifiée. Par conséquent, votre entrée aura toujours la valeur que vous avez spécifiée, dans ce cas, une boolean est toujours false par défaut.

Vous pouvez maintenant penser que votre élément d’entrée a une valeur false et que, par exemple, ajouter le checked="checked"ne le sera pas changer la valeur en true, puisque les attributs value remplacent l’attribut checked. Causer une mauvaise implémentation des deux attributs.

Par conséquent, vous devez utiliser un seul des attributs. (Soit le value ou le checked). Vous pouvez les utiliser, pour plus de commodité. Mais dans ce cas, vous devez utilisez l'attribut checked par défaut. Puisque vous implémentez Tag Helper et que la valeur en entrée doit être de type boolean. Et la valeur de l'attribut checked, renvoie un booléen et, par exemple, est celui utilisé par l'assistant de balise.

Donc, l'implémentation fournie par @dotnetstep devrait fonctionner, car elle ne déclare que le tag helper dans l'élément input. Ainsi, l’assistant de balise gère lui-même les attributs correspondants de l’entrée.

@model GroupIndexViewModel
<form asp-action="Index" asp-controller="Group" method="get">
    <ul>
        @for (var i = 0; i < Model.Filters.Count; i++)
        {
            <li>       
                <input type="checkbox" asp-for="@Model.Filters[i].Selected"  />
                <label asp-for="@Model.Filters[i].Selected">@Model.Filters[i].Name</label>
                <input type="hidden" asp-for="@Model.Filters[i].Id" />
                <input type="hidden" asp-for="@Model.Filters[i].Name" />                
            </li>
        }
    </ul>
    <button type="submit" name="action">Filtrer</button>
</form>
9
Svenja Reißaus

En me basant sur la réponse de @ dotnetstep, j'ai créé un assistant de tag qui prend un modèle de IEnumerable de SelectListItem et génère les champs décrits dans sa réponse.

Voici le code Tag Helper:

[HtmlTargetElement(Attributes = "asp-checklistbox, asp-modelname")]
public class CheckListBoxTagHelper : TagHelper
{
    [HtmlAttributeName("asp-checklistbox")]
    public IEnumerable<SelectListItem> Items { get; set; }

    [HtmlAttributeName("asp-modelname")]
    public string ModelName { get; set; }

    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        var i = 0;
        foreach (var item in Items)
        {
            var selected = item.Selected ? @"checked=""checked""" : "";
            var disabled = item.Disabled ? @"disabled=""disabled""" : "";

            var html = $@"<label><input type=""checkbox"" {selected} {disabled} id=""{ModelName}_{i}__Selected"" name=""{ModelName}[{i}].Selected"" value=""true"" /> {item.Text}</label>";
            html += $@"<input type=""hidden"" id=""{ModelName}_{i}__Value"" name=""{ModelName}[{i}].Value"" value=""{item.Value}"">";
            html += $@"<input type=""hidden"" id=""{ModelName}_{i}__Text"" name=""{ModelName}[{i}].Text"" value=""{item.Text}"">";

            output.Content.AppendHtml(html);

            i++;
        }

        output.Attributes.SetAttribute("class", "th-chklstbx");
    }
}

Vous devrez ajouter les éléments suivants au fichier _ViewImports.cshtml:

@addTagHelper *, <ProjectName>

Ensuite, pour déposer la liste de contrôle dans votre vue rasoir, rien de plus simple:

<div asp-checklistbox="Model.Brands" asp-modelname="Brands"></div>

Vous remarquerez peut-être que j'ai ajouté un attribut de classe à la div pour styliser la boîte et son contenu. Voici le CSS:

.th-chklstbx {
  border: 1px solid #ccc;
  padding: 10px 15px;
  -webkit-border-radius: 5px ;
  -moz-border-radius: 5px ;
  -ms-border-radius: 5px ;
  border-radius: 5px ; 
}
.th-chklstbx label {
    display: block;
    margin-bottom: 10px; 
}
3
gsxrboy73

Je viens d'essayer cela et cela a fonctionné:

<input asp-for="filter.type[i].IsEnabled"/>

sans la case à cocher, puis la valeur booléenne correspondante dans le modèle avec un identifiant et un nom masqués.

0
user1392916