Reputation: 803
My custom validation will validate whether or not a zip code entered into a form field is valid for a state chosen from a dropdown in the preceeding field. It works fine when I first select a state and then type in a valid/invalid zip. However, if it validates and then I go and choose a different state the validation error message does not trigger. Can anyone tell me what I am missing and why it is not re-validating?
Custom Validation:
ko.validation.rules["isValidZipCode"] =
{
async: true,
getValue: function (o) {
return (typeof o === 'function' ? o() : o);
},
validator: function (val, fields, callBack) {
var self = this;
var anyOne = ko.utils.arrayFirst(fields, function (field) {
var val = self.getValue(field);
if (val === undefined || val === null)
return "";
return true;
});
var ajaxData = { state: anyOne, zipCode: val }
$.ajax({
url: $("a#ValidateZipByState").attr("href"),
type: "POST",
data: ajaxData,
success: function (isValid) {
if (isValid) {
callBack(true);
} else {
callBack(false);
}
},
error: handleSubmitError
});
return;
},
message: "Invalid zip code for this state"
};
ViewModel:
self.State = ko.observable(model.State).extend({ required: true });
self.ZipCode = ko.observable(model.ZipCode).extend({ required: true, pattern: /^[0-9]{5}(?:-[0-9]{4})?$/g, isValidZipCode: [self.State, self.ZipCode] });
Upvotes: 1
Views: 754
Reputation: 4304
It looks like the validation rule is only attached to the ZipCode observable so updating the State value by itself would not trigger a new validation. You would have to update the state and then make another change to the zipcode before an update happens if I'm understanding the problem correctly.
If so you might want to try this quick hack to get the validation to update when the State is changed:
self.State.subscribe(function(newValue){
self.ZipCode.valueHasMutated();
});
Upvotes: 0
Reputation: 1790
You can add a subscription to State and use the ko.validation.validateObservable method to trigger the validation on ZipCode -- also, since this validation rule is specific to ZipCode you could use an anonymous custom rule.
self.State = ko.observable("StateB").extend({
required: true
});
self.State.subscribe(function(){
ko.validation.validateObservable(self.ZipCode);
})
self.ZipCode = ko.observable(789).extend({
validation: {
async: true,
validator: function (val, params, callback) {
setTimeout(function() {
var zips = stateZips.get(self.State());
var exists = zips.some(function(zip) {
return zip == new Number(val);
});
return callback(exists);
});
},
message: "Invalid zip code for this state"
}
});
Complete example here: JSFiddle
EDIT: In order to make State trigger the validation (without changing ZipCode first) you have to use:
ko.validation.init({ messagesOnModified: false });
Upvotes: 1