小数,逗号和客户端validation问题
我正在尝试为nullable
为nullable
实现客户端validation,其小数分隔符可以是逗号(例如:123,45)。
在我看来:
... @Html.LabelFor(model => model.Turnover) @Html.EditorFor(model => model.Turnover) @Html.ValidationMessageFor(model => model.Turnover) ... @section Scripts { @Styles.Render("~/Content/themes/base/css") @Scripts.Render("~/bundles/jquery") @Scripts.Render("~/bundles/jqueryui") @Scripts.Render("~/bundles/jqueryval") @Scripts.Render("~/bundles/jQueryFixes") ...scripts for this view... }
我的jQueryFixes覆盖了range()
和number()
jquery.validate.js
文件:
$.validator.methods.range = function (value, element, param) { var globalizedValue = value.replace(",", "."); return this.optional(element) || (globalizedValue >= param[0] && globalizedValue <= param[1]); } $.validator.methods.number = function (value, element) { return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:[\s\.,]\d{3})+)(?:[\.,]\d+)?$/.test(value); }
……正如关于这个问题的许多post/问题所建议的那样(例如: 这里或这里 )。
很奇怪的是:
当我尝试提交一个像123,45这样的值时,即使我用Firebug调试了脚本并看到我的overrode函数被调用并返回true,我也无法提交表单。 相反,我的EditorFor for decimal值因为任何原因而被集中,我似乎无法找出原因。
(我相信我的服务器端validation – 使用自定义绑定器等 – 工作正常,这不是问题 :我想要一些帮助,如何让表单提交或为什么输入字段集中即使它看起来有效。)
编辑1:
附加信息。 在我的BundlesConfig.cs中:
bundles.Add(new ScriptBundle("~/bundles/jquery").Include( "~/Scripts/jquery-{version}.js")); ... bundles.Add(new ScriptBundle("~/bundles/jqueryui").Include( "~/Scripts/jquery-ui-{version}.js")); bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include( "~/Scripts/jquery.unobtrusive*", "~/Scripts/jquery.validate*")); bundles.Add(new ScriptBundle("~/bundles/jQueryFixes").Include( "~/Scripts/jQueryFixes.js")); ...
编辑2:
在@LeftyX建议之后,我尝试使用Globalize脚本(在删除我的jQueryFixes.js之后):
... $( document ).ready(function() { Globalize.culture("en-US", "pt-PT"); }); $.validator.methods.number = function (value, element) { return this.optional(element) || jQuery.isNumeric(Globalize.parseFloat(value)); } //Fix the range to use globalized methods jQuery.extend(jQuery.validator.methods, { range: function (value, element, param) { var val = Globalize.parseFloat(value); return this.optional(element) || (val >= param[0] && val <= param[1]); } }); ...
…但我仍然面临同样的问题: validator.methods.number
返回true但表单未提交,输入字段被重点关注。
如果我在提交时检查输入元素,我可以看到它很快从class="valid"
变为class='input-validation-error'
然后又变回valid
。 很奇怪。
结论:
@LeftyX为发现相同问题的人提供了一个非常好的完整解决方案。
我已经有了一个可以为空的小数的自定义模型绑定器,但全球化脚本和包含Model / ViewModel中的文化肯定会派上用场。
我的问题的另一个原因可能是我(意外)包括一些脚本两次。
更新(2015年7月):
globalize.js现在有点不同了。 参考。 这个答案和更新步骤的文档 。
我对此很挣扎。
对我来说最好的方法是为小数定义一个自定义绑定器:
public class DecimalModelBinder : IModelBinder { public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { ValueProviderResult valueResult = bindingContext.ValueProvider .GetValue(bindingContext.ModelName); ModelState modelState = new ModelState { Value = valueResult }; object actualValue = null; try { //Check if this is a nullable decimal and a null or empty string has been passed var isNullableAndNull = (bindingContext.ModelMetadata.IsNullableValueType && string.IsNullOrEmpty(valueResult.AttemptedValue)); //If not nullable and null then we should try and parse the decimal if (!isNullableAndNull) { actualValue = Convert.ToDecimal(valueResult.AttemptedValue, CultureInfo.CurrentCulture); } } catch (FormatException e) { modelState.Errors.Add(e); } bindingContext.ModelState.Add(bindingContext.ModelName, modelState); return actualValue; } }
并将其绑定在Global.asax
中的Application_Start
中:
ModelBinders.Binders.Add(typeof(decimal), new DecimalModelBinder()); ModelBinders.Binders.Add(typeof(decimal?), new DecimalModelBinder());
我还使用了globalize脚本(带有文化),可以在这里找到或者从nuget下载。
你的包应该是这样的:
bundles.Add(ScriptBundle("~/bundles/jquery").Include( "~/Scripts/jquery-{version}.js", "~/Scripts/globalize.js", "~/Scripts/cultures/globalize.culture.en-GB.js", "~/Scripts/cultures/globalize.culture.it-IT.js" ));
当然,如果要支持不同的本地化,可以添加更多的文化。
现在,当您的DOM准备就绪(javascript)时,您可以定义您的文化:
Globalize.culture('en-GB'); $.validator.methods.number = function (value, element) { return this.optional(element) || jQuery.isNumeric(Globalize.parseFloat(value)); } //Fix the range to use globalized methods jQuery.extend(jQuery.validator.methods, { range: function (value, element, param) { var val = Globalize.parseFloat(value); return this.optional(element) || (val >= param[0] && val <= param[1]); } }); $.validator.methods.date = function (value, element) { return (this.optional(element) || Globalize.parseDate(value)); }
并自定义您的validation(我也添加了日期)。 你已经在jQueryFixes
完成了。
您可以在这里找到一个工作示例(MvcAppForDecimals),您可以使用工具栏和cookie更改语言,以便文化也可以在服务器上更改。
在示例中,我在Application_BeginRequest
读取cookie或使用web.config中的默认文化定义:
我还定义了一个ActionFilter(LanguageFilterAttribute),它在基本视图模型中注入当前文化,以便客户端使用服务器端的当前集合。
可在此处找到扩展说明。
有关全球化脚本和文化设置的更多信息,请点击此处 。
关于globalize.js的一个小更新。 现在情况有点不同(而且令人困惑):
包括脚本如下:
现在我们需要将I18n内容加载到Globalize :
I18n内容在此处以JSON格式提供。
如果你的getJSON()
上有404,请记得添加:
(...)
在您的Web.config(ASP .NET MVC应用程序)中。