如何模仿 LabelFor 的 aspnet mvc 代码



我的"未增强"代码如下所示:

@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("&nbsp");
        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发送(。

最新更新