MVC 3 Проверка jQuery / глобализация числа / десятичного поля

При использовании globalization culture="da-DK" в файле Web.config проверка jQuery не работает.

В Дании мы используем нотацию 19,95 вместо американской 19,95, когда пишем цену на товар, и это поставило меня перед проблемой, которую я не могу решить.

Я запустил VS2010, новый проект MVC 3, добавил homeController, класс Product и простое стандартное представление редактирования, и ошибка уже есть.

Класс продукта:

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

SO - при запуске веб-сайта поле будет установлено на 19,00 - что является правильным определением культуры - но при попытке сохранения проверка не проходит.

Пожалуйста помоги...

9 ответов

Решение

Вы можете попробовать плагин jQuery Globalization от Microsoft:

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

<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>

Подробнее об этом в блоге Скотта Хансельмана


Обновлен скрипт для текущей версии https://github.com/jquery/globalize с поддержкой дополнительных элементов

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

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

@shatl имеет правильный ответ на сегодняшний день. Обратите внимание, что для атрибута range вам понадобится взлом, показанный ниже. Полный код для добавления показан ниже:

@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>
}

В итоге я последовал совету в блоге Скотта Хансельмана на эту тему - вы можете прочитать об этом здесь:

http://www.hanselman.com/blog/GlobalizationInternationalizationAndLocalizationInASPNETMVC3JavaScriptAndJQueryPart1.aspx

Мне пришлось внести некоторые изменения, чтобы использовать Globalize вместо jQuery Global (сейчас jQuery Global мертв). Я написал это в следующем сообщении в блоге на случай, если это будет полезно:

http://icanmakethiswork.blogspot.co.uk/2012/09/globalize-and-jquery-validate.html

Просто для дальнейшего использования у меня сработало следующее:

Не забудьте установить правильную версию 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>

Нет плагинов

Я думаю, что самый простой способ обойти это без какого-либо плагина - это просто переопределить проверку по умолчанию, например так:

<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 вы увидите, что он просто проверяет регулярное выражение, как в приведенном выше коде, плюс проверяет, является ли элемент необязательным:

После некоторых исследований... я нашел решение.

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>

После этих изменений я могу манипулировать десятичными числами с помощью моего веб-интерфейса.

С уважением, Джакомо

Я из Аргентины, и я давно борюсь с этой проблемой, мы используем "," в качестве десятичного разделителя, если вы пишете "запятая", проверка 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 на язык, который вы хотите.

2-й - если вы хотите разрешить десятичную числовую клавиатуру, вы должны заменить "." с "," для правильной работы добавьте этот код на свою страницу, чтобы сделать это автоматически:

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

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

});

Престо, проблема решена.

До свидания.

Спасибо за эту страницу, избавил меня от многих проблем, мне пришлось как-то исправить код глобализации. Шведская культура не принимает точку в качестве разделителя, но поскольку parseFloat использует базовый javasacript, точки разбора будут приниматься в качестве десятичного разделителя, но на стороне сервера они будут отклонены. Чтобы это исправить, я перезаписываю 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, так что, возможно, это будет исправлено

Другие вопросы по тегам