【问题标题】:Make EditorFor render decimal value as type="text" not type="number"使 EditorFor 将十进制值呈现为 type="text" 而不是 type="number"
【发布时间】:2019-01-31 18:38:36
【问题描述】:

我在模型类中有两个属性:

public int? IntTest { get; set; }
public decimal? DecimalTest { get; set; }

然后我用它渲染:

@Html.EditorFor(model => model.IntTest, new { htmlAttributes = new { @class = "form-control"} })
@Html.EditorFor(model => model.DecimalTest, new { htmlAttributes = new { @class = "form-control"} })

我希望它们都呈现为数字类型的 html 输入,但小数点没有,我明白了:

<input class="form-control text-box single-line" data-val="true" data-val-number="The field IntTest must be a number." id="IntTest" name="IntTest" type="number" value="" />
<input class="form-control text-box single-line" data-val="true" data-val-number="The field IntTest must be a number." id="DecimalTest" name="DecimalTest" type="text" value="" />

十进制值呈现为type="text",而int 注册为type="number"

This question 暗示这不是预期的行为,所以我做错了什么吗?

如果这是预期的行为,是否有任何方法可以更改 EditorFor 以将所有小数呈现为 type="number",而不必在每个小数字段的 htmlAttributes 中添加 type = "number"

【问题讨论】:

  • 你需要使用 EditorFor 吗?你考虑过使用TextBoxFor 吗?
  • @Shyju 我很确定我对 TextBoxFor 也有相同的行为 - TextBoxFor 是否应该生成 type = "number" 的输入?

标签: razor asp.net-mvc-5 html-input editorformodel


【解决方案1】:

您看到的 html 是默认行为。 EditorFor() 方法使用TemplateHelpers.cs 中定义的默认模板(除非您为该类型创建了自定义EditorTemplate)。

对于 typeof int(以及 bytelong),它使用 NumberInputTemplate,对于 typeof decimal,它使用 DecimalTemplate。这些模板在DefaultEditorTemplates.cs 中定义,用于decimal

internal static string DecimalTemplate(HtmlHelper html)
{
    if (html.ViewContext.ViewData.TemplateInfo.FormattedModelValue == html.ViewContext.ViewData.ModelMetadata.Model)
    {
        html.ViewContext.ViewData.TemplateInfo.FormattedModelValue = String.Format(CultureInfo.CurrentCulture, "{0:0.00}", html.ViewContext.ViewData.ModelMetadata.Model);
    }
    return StringTemplate(html);
}

依次调用

internal static string StringTemplate(HtmlHelper html)
{
    return HtmlInputTemplateHelper(html);
}

对于int

internal static string NumberInputTemplate(HtmlHelper html)
{
    return HtmlInputTemplateHelper(html, inputType: "number");
}

请注意,NumberInputTemplateinputType 定义为添加type="number" 属性的"number",而StringTemplate 使用默认的inputType 生成type="text"

要为decimal 添加type="number",则需要手动添加属性,使用任一

@Html.EditorFor(m => m.DecimalTest, new { htmlAttributes = new { type = "number", @class = "form-control"} })

@Html.TextBoxFor(m => m.DecimalTest, new { type = "number", @class = "form-control"})

另一种方法是在 /Views/Shared/EditorTemplates/Decimal.cshtml 中为 typeof decimal 创建一个自定义 EditorTemplate,例如

@model decimal?
@{
    var attributes = HtmlHelper.AnonymousObjectToHtmlAttributes(ViewData["htmlAttributes"]);
    if (!attributes.ContainsKey("type"))
    {
         attributes.Add("type", "number");
    }
    string formatString = ViewData.ModelMetadata.DisplayFormatString ?? "{0:N2}";
}
@Html.TextBoxFor(m => m, formatString , attributes)

在主视图中使用

@Html.EditorFor(model => model.DecimalTest, new { htmlAttributes = new { @class = "form-control"} })

另一种选择是创建您自己的 HtmlHelper 扩展方法(例如 @Html.DecimalFor(...))来生成 html。

【讨论】:

  • 这很有趣,开辟了我不知道存在的全新事物的一面,并真正帮助我理解了这种行为。非常感谢您花时间解释它。我没有意识到传统的 aspnet 源代码是在线的,我要去那里好好挖掘一下!
  • 其实,一个follow on question;你知道为什么这是小数的默认行为吗?是否允许逗号作为小数分隔符?
  • 我猜它与精度有关 - 如何显示小数位,如果您说 2,那么您是否希望步长为 0.01,这将永远增加通过按钮使使用它有点毫无意义(它与小数分隔符无关)
  • 两个优点 - 我已经在我的代码中通过 CSS 杀死了微调器。我通过添加一个 if 语句来检查 type 属性是否已经存在,对您的代码进行了一项更改,这意味着它可以根据具体情况从代码中覆盖,并且如果用户已经设置,则不会出错类型:if (!attributes.ContainsKey("type")) { attributes.Add("type", "number"); }。如果您认为这是一个很好的补充,请务必更新您的答案以包含它。
  • @tomRedox。更新了 :) - 当然,您还可以进行许多其他增强,例如从 ModelMetadata 读取任何格式字符串并应用该格式或应用默认值(如果适用)。但是出于兴趣,如果您已移除微调器,为什么还要使用type="number"
猜你喜欢
  • 2012-10-09
  • 1970-01-01
  • 2017-06-04
  • 2016-03-24
  • 2012-05-19
  • 1970-01-01
  • 1970-01-01
  • 2011-10-03
相关资源
最近更新 更多