Пользовательский помощник для создания HTML-тегов для переключателя и соответствующей метки
Я искал решение о переключателях и соответствующих ярлыках. Мне нравится, как мы можем выбрать каждую радио-кнопку, нажав на ярлык, связанный. По умолчанию это работает не очень хорошо. Я имею в виду, что ярлыки неправильно связаны с переключателями.
Пример: допустим, у нас есть свойство с именем Revoked с возможными значениями Да / Нет. Мы хотели бы использовать переключатели, чтобы позволить пользователю выбрать значение.
Проблема: когда HTML-теги генерируются из MVC (Html.LabelFor, Html.RadioButtonFor), идентификаторы обеих радиокнопок (Да / Нет) совпадают. Таким образом, невозможно связать каждую метку с соответствующей радиокнопкой.
Решение: я создал свой собственный помощник для генерации HTML-тегов с правильным и уникальным идентификатором.
Вот мой помощник:
public static MvcHtmlString RadioButtonWithLabelFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object value, object labelText)
{
object currentValue = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData).Model;
string property = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData).PropertyName;
// Build the radio button html tag
TagBuilder htmlRadio = new TagBuilder("input");
htmlRadio.MergeAttribute("type", "radio");
htmlRadio.MergeAttribute("id", property + value);
htmlRadio.MergeAttribute("name", property);
htmlRadio.MergeAttribute("value", (string)value);
if (currentValue != null && value.ToString() == currentValue.ToString()) htmlRadio.MergeAttribute("checked", "checked");
// Build the label html tag
TagBuilder htmlLabel = new TagBuilder("label");
htmlLabel.MergeAttribute("for", property + value);
htmlLabel.SetInnerText((string)labelText);
// Return the concatenation of both tags
return MvcHtmlString.Create(htmlRadio.ToString(TagRenderMode.SelfClosing) + htmlLabel.ToString());
}
Это работает, но мне нужно посоветовать. Как вы думаете? Это эффективно? Я все еще новичок в мире ASP.NET MVC, поэтому любая помощь очень ценится.
Благодарю.
1 ответ
Помимо некоторых незначительных улучшений, которые могут быть сделаны, помощник выглядит хорошо:
- Вам не нужно звонить
ModelMetadata.FromLambdaExpression
дважды с одинаковыми аргументами - Для создания идентификатора вы объединяете имя свойства со значением, но это значение может содержать любые символы, в то время как идентификатор в HTML допускает только определенные символы. Вы должны продезинфицировать это.
- Вы преобразуете значение и currentValue в строки, которые могут завершиться с ошибкой, если помощник используется в каком-либо другом типе свойства. В этом случае либо заставьте помощника работать только со строковыми свойствами, отражая подпись помощника, либо используйте
Convert.ToString()
,
Вот переработанная версия, которая учитывает эти замечания:
public static IHtmlString RadioButtonWithLabelFor<TModel, TProperty>(
this HtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, TProperty>> expression,
TProperty value,
string labelText
)
{
var metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
object currentValue = metadata.Model;
string property = metadata.PropertyName;
// Build the radio button html tag
var htmlRadio = new TagBuilder("input");
htmlRadio.GenerateId(property + value);
htmlRadio.Attributes["type"] = "radio";
htmlRadio.Attributes["name"] = property;
htmlRadio.Attributes["value"] = Convert.ToString(value);
if (object.Equals(currentValue, value))
{
htmlRadio.Attributes["checked"] = "checked";
}
// Build the label html tag
var label = new TagBuilder("label");
label.Attributes["for"] = htmlRadio.Attributes["id"];
label.SetInnerText(labelText);
// Return the concatenation of both tags
return new HtmlString(
htmlRadio.ToString(TagRenderMode.SelfClosing) + label.ToString()
);
}