Reputation: 1981
I'm working on a web application with knockout.js and knockout validation.
I have one view model like this:
var viewModel = {
prop1 : ko.observable().extend({number:true}),
prop2 : ko.observable().extend({number:true}),
prop3 : ko.observable().extend({number:true}),
save : function () {
var vmValidatable = ko.validatedObservable(viewModel);
if (!vmValidatable.isValid())
return false;
}
}
On front-end if I try to save one number with decimal separator comma instead of a point my save function return false.
For example: if prop1 have "1.2" value the save function work correctly else if prop1 have "1,2" value the save function return false.
Can you help me please?
Thank you a lot
Upvotes: 0
Views: 575
Reputation: 23372
Here's the source for the number
extender you're using:
// https://github.com/Knockout-Contrib/Knockout-Validation/blob/master/src/rules.js#L221
ko.validation.rules['number'] = {
validator: function (value, validate) {
if (!validate) { return true; }
return ko.validation.utils.isEmptyVal(value) ||
(validate && /^-?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(value));
},
message: 'Please enter a number.'
};
I'm no regexp expert, but it looks like "," separated numbers are only supported when they separate 3 digits. I.e.: you cannot use commas to mark a decimal point.
console.log(/^-?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test("100,000"))
console.log(/^-?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test("100,000.00"))
console.log(/^-?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test("1,2"))
console.log(/^-?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test("1,200"))
You could add another extender to remove ,
characters if entered values are tested to not match the pattern. Not sure if it's a good idea though.
var test = function(val) {
if (!val) return true;
return /^-?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(val);
};
ko.extenders.removeCommas = function(target, option) {
var result = ko.pureComputed({
read: target,
write: function(newValue) {
var current = target(),
valueToWrite = test(newValue) ? newValue : newValue.replace(/,/g,
".");
if (valueToWrite !== current) {
target(valueToWrite);
} else {
if (newValue !== current) {
target.notifySubscribers(valueToWrite);
}
}
}
}).extend({
notify: 'always'
});
result(target());
return result;
};
var ViewModel = function() {
this.input = ko.observable().extend({
removeCommas: true
});
}
ko.applyBindings(new ViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<input data-bind="textInput: input" />
Upvotes: 0