【问题标题】:Radio Button Tag Helpers in ASP.NET 5 MVC 6ASP.NET 5 MVC 6 中的单选按钮标记帮助程序
【发布时间】:2016-01-02 21:26:52
【问题描述】:

我在 ASP.NET 5 MVC 6 中没有看到任何单选按钮的标签助手。在我需要使用单选按钮的情况下,处理表单元素的正确方法是什么?

【问题讨论】:

    标签: c# asp.net-mvc asp.net-core asp.net-core-mvc tag-helpers


    【解决方案1】:

    所有输入类型都有一个 TagHelper,其中也包括单选按钮类型。假设你有这样的视图模型

    public class CreateUserVm
    {
        public string UserName { set; get; }
        public IEnumerable<RoleVm> Roles { set; get; } 
        public int SelectedRole { set; get; }
    }
    public class RoleVm
    {
        public int Id { set; get; }
        public string RoleName { set; get; }        
    }
    

    在您的 GET 操作中,

    public IActionResult Index()
    {
        var vm = new CreateUserVm
        {
            Roles = new List<RoleVm>
            {
                new RoleVm {Id = 1, RoleName = "Admin"},
                new RoleVm {Id = 2, RoleName = "Editor"},
                new RoleVm {Id = 3, RoleName = "Reader"}
            }
        };
        return View(vm);
    }
    

    在视图中,您可以简单地对输入标签使用标记。

    @model YourNamespaceHere.CreateUserVm
    <form asp-action="Index" asp-controller="Home">
        <label class="label">User name</label>
        <div class="col-md-10">
            <input type="text" asp-for="UserName" />
        </div>
        <label class="label">Select a Role</label>
        <div class="col-md-10">
        @foreach (var item in Model.Roles)
        {
           <input asp-for="SelectedRole" type="radio" value="@item.Id" /> @item.RoleName
        }
        </div>
        <input type="submit" />
    </form>
    

    当您发布表单时,所选角色的 Rold Id 将位于 SelectedRole 属性中

    请记住,上面的 razor 代码将为循环生成的每个输入生成具有 same Id 属性值和 name 属性值的输入元素。在上面的示例中,它将生成 3 个输入元素(单选按钮类型),其中 Idname 属性值设置为 SelectedRole。当name 属性值与我们的视图模型中的属性名称(SelectedRole)匹配时,模型绑定将起作用,但重复的 Id 属性值可能会给您带来客户端代码的麻烦(文档中的重复 Ids 无效)

    【讨论】:

    • 我在单选按钮上使用 JS 点击事件来提交表单,但是单选按钮的值永远不会传递给我的操作方法。我是否必须将无线电输入上的名称或 id 属性设置为特定的东西?
    • 问题:我可以将值设置为真还是假? value="true"?
    • 如果这是您在选择单选按钮时想要传递的内容
    • 这不会在浏览器控制台中产生错误吗?和我一样,ASP.Net 核心(我认为)为每个无线电输入生成相同的 Id。
    • 显然现在的解决方法是手动设置id html 属性以覆盖标签助手行为。
    【解决方案2】:

    虽然有使用asp-for="SomeField" 的解决方案,但我发现最简单的解决方案是将视图模型字段与单选按钮的name 字段匹配。

    查看模型:

    public class MyViewModel
    {
       public string MyRadioField { get; set; }
    }
    

    表格(为清楚起见没有标签):

    @model MyViewModel
    <form asp-action="SomeAction" asp-controller="SomeController">
       <input type="radio" name="MyRadioField" value="option1" checked />
       <input type="radio" name="MyRadioField" value="option2" />
       <input type="radio" name="MyRadioField" value="option3" />
    
       <input type="submit" />
    </form>
    

    提交表单后,MyRadioField 将填充选中单选按钮的值。

    【讨论】:

      【解决方案3】:

      我已经编写了自己的标签助手来做到这一点。它用每个枚举变量的标签和单选按钮替换 input 标签:

      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      using DigitScpi.Web.Helpers;
      using Microsoft.AspNetCore.Mvc.Rendering;
      using Microsoft.AspNetCore.Mvc.ViewFeatures;
      using Microsoft.AspNetCore.Razor.TagHelpers;
      
      namespace TagHelpers
      {
          /// Generates the radio buttons for an enum. Syntax: `<input radio asp-for="MyMappedEnumField"/>`.
          [HtmlTargetElement("input", Attributes = RadioAttributeName)]
          public class RadioButtonTagHelper : TagHelper
          {
              private const string RadioAttributeName = "radio";
              private const string ForAttributeName = "asp-for";
      
              [HtmlAttributeNotBound] [ViewContext] public ViewContext ViewContext { get; set; }
              private readonly IHtmlGenerator _generator;
      
              [HtmlAttributeName(ForAttributeName)] public ModelExpression For { get; set; }
              [HtmlAttributeName(RadioAttributeName)] public bool RadioMarker { get; set; }
      
              public RadioButtonTagHelper(IHtmlGenerator generator)
              {
                  _generator = generator;
              }
      
              /// <inheritdoc />
              public override void Process(TagHelperContext context, TagHelperOutput output)
              {
                  output.SuppressOutput();
      
                  foreach (var enumItem in For.Metadata.EnumNamesAndValues)
                  {
                      var id = VariantId(enumItem);
                      var name = For.Metadata.EnumGroupedDisplayNamesAndValues.FirstOrDefault(v => v.Value == enumItem.Value).Key.Name;
                      var radio = _generator.GenerateRadioButton(ViewContext, For.ModelExplorer, For.Name, enumItem.Key, false, new {id});
                      var label = _generator.GenerateLabel(ViewContext, For.ModelExplorer, For.Name, name, new {@for = id});
      
                      output.PreElement.AppendHtml(radio);
                      output.PreElement.AppendHtml(label);
                  }
              }
      
              /// Computes the variant to be unique for each radiobutton.
              private string VariantId(KeyValuePair<string, string> enumItem) =>
                  new StringBuilder()
                      .Append(ViewContext.CreateUniqueId(_generator.IdAttributeDotReplacement, For.Name))
                      .Append(_generator.IdAttributeDotReplacement)
                      .Append(enumItem.Key)
                      .ToString();
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2015-12-27
        • 1970-01-01
        • 2015-03-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-06-04
        • 1970-01-01
        相关资源
        最近更新 更多