ko.validation with validatedObservable gives me strange result

Bronzato picture Bronzato · Jun 3, 2013 · Viewed 9k times · Source

I use ko.validation to check valid data on my page like this:

var postcode = ko.observable(),
    name = ko.observable();

var validationModel = ko.validatedObservable({
    postcode: postcode.extend({ required: true }),
    name: name.extend({ required: true })
});

Then in my OK button I check the validation before submitting:

var buttonOk = function () {

    if (!validationModel.isValid()) {
        validationModel.errors.showAllMessages();
        return false;
    }
    ...

It works pretty well: If the user don't type something for postcode and name the validation failed.

Now I added some more validation rules:

postcodeMustNotAlreadyExists + denominationMustNotAlreadyExists like this:

var validationModel = ko.validatedObservable({
    postcode: postcode.extend({ required: true }),
    name: name.extend({ required: true })
}).extend({
    postcodeMustNotAlreadyExists: cities,
    denominationMustNotAlreadyExists: cities
});

ko.validation.rules['postcodeMustNotAlreadyExists'] = {
    validator: function (val, cities) {
        // Try to find a match between the typed postcode and the postcode in the list of cities
        var match = ko.utils.arrayFirst(cities(), function (item) {
            return (val.postcode() === item.postCode());
        });            
        return !match;
    },
    message: 'This postcode already exists!'
};
ko.validation.rules['denominationMustNotAlreadyExists'] = {
    validator: function (val, cities) {
        // Try to find a match between the typed denomination and the denomination in the list of cities
        var match = ko.utils.arrayFirst(cities(), function (item) {
            return (val.name() === item.name());
        });
        return !match;
    },
    message: 'This denomination already exists!'
};
ko.validation.registerExtenders();

Now validationModel.isValid() returns always true when the user don't type anything for postcode or name. And I noticed that validationModel().postcode.isValid() is false thus this is not logic to have validationModel.isValid() set to True.

Now with my new implementation I have to test on 2 things: (!validationModel.isValid() || validationModel().errors().length>0)

Any idea?

Thanks.

Answer

Tom Studee picture Tom Studee · Jun 5, 2013

Try overriding your isValid() function inside your viewModel with:

self.isValid = ko.computed(function () {
        return ko.validation.group(
            self,
            {
                observable: true,
                deep: true
            }).showAllMessages(true);
    }, self);