如何模仿LabelFor的aspnet mvc代码?

时间:2017-04-13 15:30:41

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

My" nonnhanced"代码如下所示:

@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>

我想知道in the aspnet mvc source code我在哪里可以找到LabelFor等的代码。

这样我就可以更好地理解它是如何工作的,并创建一个扩展函数,如:

public static IHtmlContent FullGroupFor<TModel, TResult>(this IHtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TResult>> expression);

2 个答案:

答案 0 :(得分:2)

所有LabelFor正在创建一个<label>属性for。此属性指向表单元素的id(例如文本框或复选框),并将为其提供焦点(或切换复选框)。

<label for="my-textbox">
<input id="my-textbox" type="text">

表单组没有标签。这些很可能是使用<fieldset>创建的,其<legend>标记用于显示每个集的说明。

此外,使用display: none切换组或字段集不是一个好主意,因为不会提交隐藏的表单元素。

答案 1 :(得分:0)

我选择了@ 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添加的内容也很重要,这是:&#34;用display:none切换组或字段集不是一个好主意,因为隐藏的表单元素不会被提交&# 34 ;.在我的情况下,它可以,因为它符合我的规格(如果用户未检查过该字段,则会将其作为null发送。)