use*_*392 4 javascript validation jquery asp.net-mvc-4
我正在尝试nullable<decimal>为其小数分隔符可以是逗号(例如:123,45)实现客户端验证.
在我看来:
...
<div class="editor-label">
    @Html.LabelFor(model => model.Turnover)
</div>
<div class="editor-field">
    @Html.EditorFor(model => model.Turnover)
    @Html.ValidationMessageFor(model => model.Turnover)
</div>
...
@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覆盖jquery.validate.js了range()和的文件number():
$.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);
}
......正如关于这个问题的许多帖子/问题所建议的那样(例如:这里或这里).
很奇怪的是:
当我尝试提交一个像123,45这样的值时,即使我用Firebug调试了脚本并看到我的overrode函数被调用并返回true,我也无法提交表单.相反,我的EditorFor for decimal值因为任何原因而被集中,我似乎无法找出原因.
(我相信我的服务器端验证 - 使用自定义绑定器等 - 工作正常,这不是问题:我想要一些帮助,如何提交表单或为什么输入字段集中即使它看起来有效.)
编辑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之后):
<script type="text/javascript">
    ...
    $( 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]);
        }
    });
   ...
</script>
...但我仍然面临同样的问题: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;
    }
}
并将其绑定Application_Start在Global.asax:
ModelBinders.Binders.Add(typeof(decimal), new DecimalModelBinder());
ModelBinders.Binders.Add(typeof(decimal?), new DecimalModelBinder());
我也用在全球化脚本(与文化),可以发现,在这里或下载的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));
}
并自定义您的验证(我也添加了日期).你已经完成了jQueryFixes.
您可以在这里找到一个工作示例(MvcAppForDecimals),您可以使用工具栏和cookie更改语言,以便文化也可以在服务器上更改.
在示例中,我读取了cookie Application_BeginRequest或使用web.config中的默认文化定义:
<globalization enableClientBasedCulture="true" uiCulture="en-GB" culture="en-GB" />
我还定义了一个ActionFilter(LanguageFilterAttribute),它在基本视图模型中注入当前文化,以便客户端使用服务器端的当前集合.
可在此处找到扩展说明.
有关全球化脚本和文化设置的更多信息,请点击此处.
| 归档时间: | 
 | 
| 查看次数: | 6949 次 | 
| 最近记录: |