Я не вижу никаких помощников тегов для переключателей в ASP.NET 5 MVC 6. Какой правильный способ обработки элементов формы, где мне нужно использовать радиокнопки?
Помощники тегов радио кнопки в ASP.NET 5 MVC 6
Ответ 1
Существует TagGelper для всех типов ввода, который также включает тип переключателя. Предполагая, что у вас есть такая модель вида
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 для выбранной роли будет находиться в свойстве SelectedRole
Имейте в виду, что приведенный выше код бритвы будет генерировать входной элемент с атрибутом same Id
и значением атрибута name
для каждого входа, генерируемого циклом. В приведенном выше примере он будет генерировать 3 входных элемента (тип переключателя) с атрибутом Id
и name
, установленным на SelectedRole
. Привязка к модели будет работать, так как значение атрибута name
соответствует имени свойства (SelectedRole
) в нашей модели представления, но значения атрибутов повторяющихся идентификаторов могут вызвать проблемы с кодом на стороне клиента (дубликаты идентификаторов в документе недействительны)
Ответ 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
на метку и радиокнопку для каждого варианта enum:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Mvc.ViewFeatures.Internal;
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 Dummy { get; set; }
public RadioButtonTagHelper(IHtmlGenerator generator)
{
_generator = generator;
}
/// <inheritdoc />
public override void Process(TagHelperContext context, TagHelperOutput output)
{
AssertModelIsEnum();
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.Metadata.PropertyName, 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)
{
var fullHtmlFieldName = NameAndIdProvider.GetFullHtmlFieldName(ViewContext, For.Name);
return new StringBuilder()
.Append(NameAndIdProvider.CreateSanitizedId(ViewContext, fullHtmlFieldName, _generator.IdAttributeDotReplacement))
.Append(_generator.IdAttributeDotReplacement)
.Append(enumItem.Key)
.ToString();
}
private void AssertModelIsEnum()
{
if (!For.ModelExplorer.ModelType.IsEnum)
{
throw new ArgumentException("The model bound to the radiobutton with 'RadioButtonTagHelper' must be an enum.");
}
}
}
}