I'm trying to achieve client-side validation for a nullable<decimal>
whose decimal separator can be a comma (e.g.: 123,45).
In my View:
...
<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...
}
My jQueryFixes overrides jquery.validate.js
file for the range()
and 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);
}
...as suggested in many posts/questions regarding this issue (e.g.: here or here).
Strangely enough:
When I try to submit a value such as 123,45, and even though I've debugged the script with Firebug and seen that my overrode functions are being called and returning true, I'm not being able to submit the form. Instead, my EditorFor for the decimal value is being focused for whatever reason and I can't seem to find out why.
(I believe that my server-side validation - using a custom binder, etc. - is working fine and that is not the issue here: I would like some help on how to get the form to submit or why is the input field getting focused even though it looks valid.)
EDIT 1:
Additional info. In my 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"));
...
EDIT 2:
After @LeftyX suggestion, I tried using the Globalize script (after removing my 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>
...but I still face the same issue: the validator.methods.number
is returning true but the form isn't submitted and the input field gets focused instead.
If I inspect the input element while I submit, I can see that it quickly goes from class="valid"
to class='input-validation-error'
and then back to valid
. Very strange.
CONCLUSION:
@LeftyX gave a very good and complete solution for whoever finds the same issues.
I already had a custom model binder for the nullable decimals, but the globalization script and including the culture in the Model/ViewModel sure comes in handy.
Another reason for my problem could be the fact that I was (accidentally) including some scripts twice.
UPDATE (Jul/2015):
globalize.js is a bit different now. Ref. to this answer and the documentation for the updated steps.