【问题标题】:How to mimic the aspnet mvc code for LabelFor?如何模仿 LabelFor 的 aspnet mvc 代码?
【发布时间】:2017-09-09 19:32:48
【问题描述】:

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

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

【问题讨论】:

  • 创建一个调用LabelFor的新扩展会更容易吗?从那个结果开始,然后在新的扩展方法中添加你的东西?
  • @krillgar 感谢您的提示,经过一些工作我已经发布了a solution to the problem

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


【解决方案1】:

LabelFor 所做的只是创建一个带有for 属性的&lt;label&gt;。此属性指向表单元素的 id,例如文本框或复选框,并为其提供焦点(或切换复选框)。

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

表单组没有标签。这些很可能是使用&lt;fieldset&gt; 创建的,&lt;legend&gt; 标签用于显示每个集合的说明。

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

【讨论】:

  • 感谢您的回答,我不知道display: none 会产生不提交隐藏表单元素的效果。经过一些工作,我发布了a solution to the problem。我很好奇 display: none 的替代方法来切换内容。
【解决方案2】:

我接受了@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 添加的内容也很重要,即:“使用 display: none 切换组或字段集不是一个好主意,因为不会提交隐藏的表单元素”。在我的情况下,这没关系,因为它符合我的规范(如果用户未检查,则字段将作为 null 发送)。

【讨论】:

  • 根据this answer,现代浏览器提交display:none元素。但是,他们仍然不会提交被禁用的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-24
  • 2014-06-10
相关资源
最近更新 更多