MVC 3 jQuery 验证/全球化数字/小数字段

66

在Web.config文件中使用全球化culture="da-DK"时,jQuery验证不起作用。

在丹麦,我们在为产品定价时使用19,95这种表示法,而不是美国式的19.95,这给了我一个问题,我解决不了。

我已经启动了VS2010,创建了一个新的MVC 3项目,添加了一个HomeController、一个Product类和一个简单的标准编辑视图,但错误已经存在了。

Product Class:

public class Product
{
    public string name { get; set; }
    public string itemNo { get; set; }
    public decimal price { get; set; }
}

HomeController:

public class homeController : Controller
{
    public ActionResult Index()
    {
        var product1 = new Product { name = "Testproduct", itemNo = "PRD-151541", price = 19 };
        return View(product1);
    }
}

索引视图:

@model WebUI.DomainModel.Product

<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>

@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>Product</legend>

        <div class="editor-label">
            @Html.LabelFor(model => model.name)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.name)
            @Html.ValidationMessageFor(model => model.name)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.itemNo)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.itemNo)
            @Html.ValidationMessageFor(model => model.itemNo)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.price)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.price)
            @Html.ValidationMessageFor(model => model.price)
        </div>

        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>
}

结果:

很遗憾,我无法在此处提交图片 - 请跟随此链接查看结果:http://www.designvision.dk/temp/mvc3_razor_validation_error.gif

因此,在运行网站时,该字段将设置为19.00 - 这是正确的区域定义 - 但在尝试保存时,验证失败。

请帮忙...


+1,好问题,我也遇到了同样的问题,只是针对日期。 - Darko
好问题,如果您将其发送到Microsoft Connect,那就更好了。当开发人员基于实体框架自动生成视图时,@Html.ValidationMessageFor用于小数字段的行为就像您在此处展示的一样。 - Junior Mayhé
9个回答

57
你可以尝试使用来自微软的 jQuery 全球化插件: jQuery Globalization plugin
<script src="@Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>

<script src="@Url.Content("~/Scripts/jquery.glob.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/globinfo/jquery.glob.da-dk.js")" type="text/javascript"></script>
<script type="text/javascript">
    $.validator.methods.number = function (value, element) {
        return !isNaN($.parseFloat(value));
    }

    $(function () {
        $.preferCulture('da-DK');
    });
</script>

插件已更名和移动,你应该使用 Globalize(2012年3月)

<script src="@Url.Content("~/Scripts/jquery.globalize/globalize.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.globalize/cultures/globalize.culture.da-DK.js")" type="text/javascript"></script>
<script type="text/javascript">
    $.validator.methods.number = function (value, element) {
        return !isNaN(Globalize.parseFloat(value));
    }

    $(document).ready(function () {
        Globalize.culture('da-DK');
    });
</script>

关于此更多内容请参考Scott Hanselman的博客文章


哦,这真的很奇怪——昨天我在那个网站上,但是我无法让它工作。但现在它正在运行——非常感谢! - designvision.dk
1
如果值为 "0",parseFloat 将返回 0 即 false。我是这样解决的:$.validator.methods.number = function (value, element) {return parseFloat(value).toString() !== "NaN";} - Zote
6
更好的代码来支持可选元素$.validator.methods.number = function (value, element) { return this.optional(element) || !isNaN(Globalize.parseFloat(value)); } $(function () { Globalize.culture('%%culture%%'); }); - shatl
3
过时了,或者至少对我没起作用。请查看shatl的答案以获取最新版本(对我有效)。 - lko
1
由于链接导向了 https://github.com/jquery/jquery-global/,但该页面已返回 404 错误,因此我们将标记此答案。以下是 JavaScript 文件的下载链接:http://dl.dropbox.com/u/3931391/jQuery%20Globalization%20plugin%20-%20jquery-glob%20-%20jquery-global.rar - Junior Mayhé
显示剩余3条评论

23

更新了针对https://github.com/jquery/globalize当前版本的脚本,并增加了可选元素支持。

$.validator.methods.number = function (value, element) {
   return this.optional(element) || !isNaN(Globalize.parseFloat(value));
}

$(function () {
    Globalize.culture('%%culture%%');
});

1
只需将2个脚本 globalize.jscultures/globalize.cultures.js 添加到您的HTML中,并将其放置在脚本块中即可。 - lko
这是正确的。请查看我的答案以获取完整的代码和范围技巧。 - RickAndMSFT

14

截至目前,@shatl的回答是正确的。请注意,对于range属性,您需要使用下面展示的hack。要添加完整代码,请参考下面示例:

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
    <script type="text/javascript" src="~/Scripts/globalize.js"></script>
    <script type="text/javascript" src="~/Scripts/globalize.culture.fr-FR.js"></script>
    <script type="text/javascript">
        $.validator.methods.number = function (value, element) {
            return this.optional(element) ||
                !isNaN(Globalize.parseFloat(value));
        }
        $(document).ready(function () {
            Globalize.culture('fr-FR');
        });

        jQuery.extend(jQuery.validator.methods, {    
            range: function (value, element, param) {        
                //Use the Globalization plugin to parse the value        
                var val = $.global.parseFloat(value);
                return this.optional(element) || (
                    val >= param[0] && val <= param[1]);
            }
        });
    </script>
}

1

仅供参考,以下是适用于我的解决方案:

记得设置正确的jQuery版本和正确的区域设置,例如丹麦语。
如果值中不能有句号,则取消注释。

<script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")"
    type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")"
    type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")"
    type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.globalize/globalize.js")"
    type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.globalize/cultures/globalize.culture.da-DK.js")"
    type="text/javascript"></script>
<script type="text/javascript">
        $.validator.methods.number = function (value, element) {
            // if (value.indexOf(".") >= 0) {
            //     return false;
            // }
            return (Globalize.parseFloat(value));
        }

        $(document).ready(function () {
            Globalize.culture('da-DK');
        });

        jQuery.extend(jQuery.validator.methods, {
            range: function (value, element, param) {
                //Use the Globalization plugin to parse the value
                var val = Globalize.parseFloat(value);
                return this.optional(element) || (val >= param[0] && val <= param[1]);
            }
        });
</script>

1

0

无需插件

我认为最简单的方法是通过覆盖默认验证来解决这个问题而无需任何插件,像这样:

<script type="text/javascript">
    $.validator.methods.number = function (value, element) {            
        var regex = /^(\d*)(\,\d{1,2})?$/; //99999,99
        return regex.test(value);
    }
</script>

如果您查看jquery.validate.js的源代码,您会发现它只是测试一个类似上面代码的正则表达式,并验证元素是否可选:

enter image description here


它不是一个插件,但在这种情况下可以工作。但它是标准验证插件的覆盖,而插件则扩展了不同文化的验证。扩展还将为其他类型(如日期)提供正确的验证,而脚本则不会。 - Christoph Brückmann

0

感谢这个页面,让我省了很多麻烦。不过我还得修复globalize代码。瑞典文化不接受点作为分隔符,但是由于parseFloat使用底层的javascript解析器,所以点会被接受作为十进制分隔符,但是在服务器端这些将被拒绝。为了解决这个问题,我像这样覆盖了parseFloat函数。

Globalize.orgParaseFloat = Globalize.parseFloat;
Globalize.parseFloat = function(value) {
    var culture = this.findClosestCulture();
    var seperatorFound = false;
    for (var i in culture.numberFormat) {
        if (culture.numberFormat[i] == ".") {
            seperatorFound = true;
        }
    }

    if (!seperatorFound) {
        value = value.replace(".", "NaN");
    }

    return this.orgParaseFloat(value);
};

我已经在他们的Github上开了一个工单,也许这个问题会被解决。


0
经过一些研究...我找到了一个解决方案。 Web.config<system.web>中添加。
<globalization culture="auto" uiCulture="auto" enableClientBasedCulture="true"/>

扩展 HtmlHelper 类

namespace System.Web.Mvc
{
    public static class LocalizationHelper
    {
        public static IHtmlString MetaAcceptLanguage(this HtmlHelper html)
        {
            var acceptLang = HttpUtility.HtmlAttributeEncode(Thread.CurrentThread.CurrentUICulture.ToString());
            return new HtmlString(string.Format("<meta name=\"accept-language\" content=\"{0}\"/>", acceptLang));
        }
    }
}

_Layout.cshtml<head>标签的末尾添加

@Html.MetaAcceptLanguage();
<script type="text/javascript">
    $(document).ready(function () {
        var data = $("meta[name='accept-language']").attr("content");
        $.global.preferCulture(data);
    });
</script>

在这些更改之后,我能够通过我的 Web GUI 操作十进制数。

敬礼, Giacomo


4
看起来很像Scott Hanselman的解决方案(http://www.hanselman.com/blog/GlobalizationInternationalizationAndLocalizationInASPNETMVC3JavaScriptAndJQueryPart1.aspx)。 - René
@René 如果你问我,这个解决方案有点太像Scott的了。 - Jacques

0

我来自阿根廷,已经与这个问题斗争了很长时间。我们使用“,”作为小数分隔符,如果您写“逗号”,JavaScript验证将失败,但是如果您输入“。”,模型将接收一个转换为整数的数字(55.60将变成5560)。

我用以下简单的解决方案解决了这个问题:

第一步- 我升级了jquery验证库,使用了新的cdn地址: http://jqueryvalidation.org/

我在我的JavaScript中包含的链接如下:

<script src="http://ajax.aspnetcdn.com/ajax/jquery.validate/1.13.0/jquery.validate.js"></script>
<script src="http://ajax.aspnetcdn.com/ajax/jquery.validate/1.13.0/jquery.validate.min.js"></script>
<script src="http://ajax.aspnetcdn.com/ajax/jquery.validate/1.13.0/additional-methods.js"></script>
<script src="http://ajax.aspnetcdn.com/ajax/jquery.validate/1.13.0/additional-methods.min.js"></script>

如果你想要它以特定的语言(例如西班牙语)呈现,请添加这行代码:

<script src="http://ajax.aspnetcdn.com/ajax/jquery.validate/1.13.0/localization/messages_es.js"></script>

将ES替换为您想要的语言。

第二- 如果您想允许数字键盘小数点,请将“.”替换为“,”以使其正常工作,将此代码添加到您的页面中以自动执行:

$('#txtCurrency').keyup(function () {

    $('#txtCurrency').val($('#txtCurrency').val().replace(/\./g, ','));

});

完成了,问题解决了。

再见。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接