我的"未增强"代码如下所示:
@using (Html.BeginForm("Index", "home"))
{
<!-- old group -->
<div class="form-group">
@Html.LabelFor(m => m.Query.artist)
@Html.TextBoxFor(m => m.Query.artist, new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.Query.artist)
</div>
...
}
但是我想增强它并为每个form-group
添加一个切换功能,如下所示:
<script>
var toggleProperty = function(targetCheckbox) {
var id = targetCheckbox.id.split('-')[0];
var inputDiv = document.getElementById(id + "-inputdiv");
inputDiv.style.display = (inputDiv.style.display !== "none") ? "none" : "";
}
</script>
<!-- new group -->
<input type="checkbox" id="property1-toggler" value="false" onchange="return toggleProperty(this)"/> <label for="property1">name for property1</label>
<div id="property1-inputdiv">
<input class="form-control" id="property1" name="property1" type="text" value="property1 default value">
<span class="field-validation-valid" data-valmsg-for="property1" data-valmsg-replace="true"></span>
</div>
我想知道在 aspnet mvc 源代码中哪里可以找到LabelFor
等的代码。
这样我就可以更好地理解它是如何工作的,并创建一个扩展函数,如下所示:
public static IHtmlContent FullGroupFor<TModel, TResult>(this IHtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TResult>> expression);
LabelFor
所做的只是创建一个具有for
属性的<label>
。此属性指向表单元素(如文本框或复选框(的 id,并为其提供焦点(或切换复选框(。
<label for="my-textbox">
<input id="my-textbox" type="text">
表单组没有标签。这些很可能是使用 <fieldset>
创建的,该具有用于显示每个集合的解释的标签<legend>
。
此外,使用display: none
切换组或字段集不是一个好主意,因为不会提交隐藏的表单元素。
我接受了@krillgar的建议,它奏效了:
public static class HtmlHelperExtensions
{
/// <summary>
/// Given an input property, creates a full block of:
/// 1. checkbox (to allow toggle)
/// 2. label
/// 3. extra content if needed (shown above the textbox)
/// 4. textbox
/// 5. validation message
///
/// 3+4+5 are shown only if the checkbox is clicked (toggle functionality)
/// </summary>
public static IHtmlContent FullGroupFor<TModel, TResult>(
this IHtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, TResult>> expression,
string placeholder = null,
IHtmlContent extraContent = null)
{
var propertyId = string.Join("_", expression.Body.ToString().Split('.').Skip(1));
var method = expression.Compile();
var value = method(htmlHelper.ViewData.Model);
var hasValue = (value != null);
var builder = new HtmlContentBuilder();
builder.AppendHtml("<div class="form-group">");
builder.AppendHtml($"<input type="checkbox" id="{propertyId}-toggler" {(hasValue ? "checked" : "")} onchange="return toggleProperty(this)"/>");
builder.AppendHtml(" ");
builder.AppendHtml(htmlHelper.LabelFor<TResult>(expression, null, null));
builder.AppendHtml($"<div id="{propertyId}-inputdiv" style="display:{(hasValue ? "" : "none")}">");
if (extraContent != null)
builder.AppendHtml(extraContent);
builder.AppendHtml(htmlHelper.TextBoxFor(expression, new { @class = "form-control", placeholder = placeholder }));
builder.AppendHtml(htmlHelper.ValidationMessageFor(expression));
builder.AppendHtml("</div>");
builder.AppendHtml("</div>");
return builder;
}
/// <summary>
/// Javascript code necessary to run the toggle code in the previous function.
/// </summary>
public static IHtmlContent GetToggleScript(this IHtmlHelper htmlHelper)
=> new HtmlString(@"
<script>
var toggleProperty = function(targetCheckbox) {
var id = targetCheckbox.id.split('-')[0];
var inputDiv = document.getElementById(id + '-inputdiv');
inputDiv.style.display = (inputDiv.style.display !== 'none') ? 'none' : '';
}
</script>
");
}
同样重要的是@Soviut添加的内容,即:"使用显示切换组或字段集不是一个好主意:无,因为不会提交隐藏的表单元素"。就我而言,没关系,因为它符合我的规范(如果用户未检查字段,则字段将作为null
发送(。