'knockout validator with dynamic message
I want my knockout validator to have a message that depends on the validation of the input. It seems like a very common use case but I can't find any way of doing it... here's a simplistic example of what I'd like to do
ko.validation.rules.dumb = {
validator: function( value )
{
if (value.startsWith( "s")) return {isValid:true}
return {isValid:false, message: value + " needs to start with an s"}
}
}
some_field.extend({dumb: {}});
This sort of works:
ko.validation.rules.sort_of_works = {
validator: function( value)
{
if (value.startWith("s")) return true;
ko.validation.rules.message = value + needs to start with an s";
return false;
}
}
but it really doesn't - because it only works if you only have one field using that validator :(
I tried accessing "this" in the function, but the this is the this of the validator function - which isn't useful, as it doesn't have a message on it. Also - I've seen people make message a function, so it depends on the input itself - but my validation is expensive (think something like parsing, where you want to say exactly where the error is in the string) - and I don't want to do it once for the validation, and then again for the message.
What I want works perfectly with the async validation callback function - in fact that's sort of what I'm mimicking, the validation actually happens on the server - but unfortunately the rest of the app (not written by me) is not really setup to support IsValidating - so I can't use async.
Solution 1:[1]
I think the library is designed to chain multiple validations using extend.
So, instead of having one validator function that checks a ton of cases, you create a set of validators that all do one simple check that corresponds to a single error message:
ko.validation.rules.startsWith = {
validator: (val, param) => val?.startsWith(param),
message: 'The field must start with {0}'
};
ko.validation.rules.endsWith = {
validator: (val, param) => val?.endsWith(param),
message: 'The field must end with {0}'
};
ko.validation.registerExtenders();
const myValue = ko.observable()
.extend({ startsWith: "s" })
.extend({ endsWith: "p" });
ko.applyBindings({ myValue });
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout-validation/2.0.4/knockout.validation.js"></script>
<label>
Input a word that starts with an <code>s</code> and ends with a <code>p</code><br>
<input data-bind="value: myValue">
</label>
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | user3297291 |
