65.9K
CodeProject is changing. Read more.
Home

Using Observable And Computed for Validation in Knockout

Jul 4, 2014

CPOL

1 min read

viewsIcon

17135

downloadIcon

112

Using Observable and Computed for validation in Knockout

Introduction

If we check out https://github.com/Knockout-Contrib/Knockout-Validation, we will find out how the knockout's basic and custom validations work. But sometimes, we may want to use one of the observables value to take part in the validation process. To do so, we have to use a little trick.

Background

For a quick review, check out http://jsfiddle.net/ZfUWH/.

Now let’s say we have two observables at the view model, first number and second number. And the validator should work for the validation where the first number needs to be less than the second number (first number < second number).

So we have to pass the first numbers' value to the the second numbers' validator rules, for validation.

Using the Code

Let’s say we made a custom validator rule "isLargerThan" for the validation, now we are going to use it in secondNumber observable like this.

Here, using ko.computed is important, because it is working with the observable firstNumber.

If you don't use ko.computed, the custom validator would become a regular static validator, where changeable firstNumber values would not be considered in the validation process, every time when its value changes.

/*fields*/
self.firstNumber = ko.observable('').extend({ required: true, min: 0, digit: true});
self.secondNumber = ko.observable('').extend({
    required: true,
    min: 0,
    digit: true,
    isLargerThan: ko.computed(function () {  //custom validation
        return self.firstNumber();           //assigning observable
    })
});

Here is our custom validator rule where reassigning otherVal = otherVal() is important, as we sent ko.computed function, and value is stored inside the function itself.

/*Validation: 1*/
ko.validation.rules['isLargerThan'] = {
    validator: function (val, otherVal) {
        /*important to use otherValue(), because ko.computed returns a function,
        and the value is inside that function*/
        otherVal = otherVal();                
        return parseFloat(val) > parseFloat(otherVal);
    },
    message: 'This need to be larger than the First Number '
};
ko.validation.registerExtenders();

If we want to use more observables for validation, we just only need to use more of them at the return session of ko.computed with property names, as we did in here:

self.thirdNumber = ko.observable('').extend({
    required: true,
    min: 0,
    digit: true,
    isBetween: ko.computed(function () {
        return {                            //assigning multiple observables
            firstNumber: self.firstNumber(),
            secondNumber: self.secondNumber()
        };
    })
});

/*Validation: 2*/
ko.validation.rules['isBetween'] = {
    validator: function (val, otherVal) {
        /*important to use otherValue(), because ko.computed returns a function,
        and the value is inside that function*/
        otherVal = otherVal();
        return parseFloat(val) >= parseFloat(otherVal.firstNumber)
            && parseFloat(val) <= parseFloat(otherVal.secondNumber);
    },
    message: 'This need to be between than the First Number and Second number'
};
ko.validation.registerExtenders();