Search code examples
javascriptknockout.jsknockout-validation

Knockout Validation custom rules are not working


I am unable to get custom rules to work. I'm afraid I'm failing to understand something fundamental. In this example, b, bvm and berr all validated as expected off of the required extender. Against my custom extender foo, a,avm and aerr do not fail validation as expected.

Calling console.log() from within validator demonstrates that the validator is not being fired. The only way I was able to get the validator function to fire is by calling ko.registerExtenders after the init (although there is no reason to do this, registerExtenders is enabled by default. If it is called, validator is triggered when I reference the extender creating the observable array.

Here's my fiddle.

ko.validation.init({
    grouping: {
        deep: true,
        live: true,
        observable: true
    }
});

ko.validation.rules['foo'] = {
    validator: function(arr) {
        if (!arr.length) {
            return false;
        } else {
            return true;
        }
    },
    message: 'Please foo.'
};
var a = ko.observableArray().extend({ foo: true });
var avm = ko.validatedObservable({
    a: a
});
var aerr = ko.validation.group([a]);

var b = ko.observableArray().extend({ required: true });
var bvm = ko.validatedObservable({
    b: b
});
var berr = ko.validation.group([b]);    

Solution

  • The placement of the init isn't as critical as having a call to registerExtenders after your custom extender. If you omit that line the custom extenders will just be ignored, as you've experienced.

    https://jsfiddle.net/c7xynchp/12/

    var log = console.debug.bind(console, '[Debug]');
    ko.validation.rules['foo'] = {
        validator: function(arr) {
            log('validator', arguments);
            if (!arr.length) {
                log('invalid');
                return false;
            } else {
                log('valid', arr);
                return true;
            }
        },
        message: 'Please select at least one vendor.'
    };
    ko.validation.registerExtenders();
    var a = ko.observableArray().extend({ foo: true });
    var avm = ko.validatedObservable({
        a: a
    });
    var aerr = ko.validation.group([a]);
    
    var b = ko.observableArray().extend({ required: true });
    var bvm = ko.validatedObservable({
        b: b
    });
    var berr = ko.validation.group([b]);
    ko.validation.init({
        grouping: {
            deep: true,
            live: true,
            observable: true
        }
    });
    
    log('a', a.isValid());
    log('avm', avm.isValid());
    log('aerr', aerr());
    log('b', b.isValid());
    log('bvm', bvm.isValid());
    log('berr', berr());
    
    // just for laughs
    log('aberr', ko.validation.group([a,b])());