2

I have the following javascript code

function AppViewModel(){
    this.myValue = ko.observable().extend({ minNumber: "5"}).extend({ maxNumber: "20" });
}

ko.extenders.minNumber = function(target, minValue){
    target.hasError = ko.observable();
    target.errorMessage = ko.observable();

    function validate(newValue){
        target.hasError(parseInt(newValue) < parseInt(minValue) ? true : false);
        target.errorMessage(parseInt(newValue) < parseInt(minValue) ? "MinVal" : "");
    }

    validate(target());

    target.subscribe(validate);

    return target;
};

ko.extenders.maxNumber = function(target, maxValue){
    target.hasError = ko.observable();
    target.errorMessage = ko.observable();

    function validate(newValue){
        target.hasError(parseInt(newValue) > parseInt(maxValue) ? true : false);
        target.hasError(parseInt(newValue) > parseInt(maxValue) ? "MaxVal" : "");
    }

    validate(target());

    target.subscribe(validate);

    return target;
};

ko.applyBindings(new AppViewModel());

and the following HTML

<input data-bind="value: myValue, valueUpdate: 'afterkeydown'"/><br/>
<span data-bind="text: myValue"></span>
<span data-bind="text: myValue.errorMessage"></span>
<span data-bind="text: myValue.hasError"></span>

What I am trying to achieve is a validation on an observable with a minimum and maximum integer value. My code works http://jsfiddle.net/Gazzo100uk/nCtpx/5/ but I am unsure as to why it works for instance why does the maxNumber not clear the errorMessage property in its validate function even if the integer is less than 5 in this example or vice versa for the min.

What order will these functions be fired?

Like I say, it does what I want it to do but I don't understand how it is working and to be honest I never expected it to work.

Can anybody shed any light please?

Regards, Gary

Gary F
  • 360
  • 3
  • 12
  • I have decided to change the observable names in my extend methods to be different as in this fiddle http://jsfiddle.net/Gazzo100uk/nCtpx/8/ as I wasn't too happy putting in the previous code not understanding how it worked. – Gary F May 21 '13 at 13:35
  • Just out of curiosity, why aren't you using knockout-validation? (https://github.com/Knockout-Contrib/Knockout-Validation) If you have tried knockout-validation and decided not to use it, I'd like to know your reasoning. – Jeff Jan 29 '14 at 19:01
  • 1
    Hi Jeff, I didn't use the knockout-validation for various reasons, at the time I was only doing server side development so the whole javascript world was new to me so getting to grips with knockout itself was enough. On top of that it was extremely easy to extend an observable and as we progressed with our validation we needed more complex validations i.e. validating one observable dependant on the value of two others Then further requirements meant that we were validating an observable using a custom function passed in to the extend method. At this point deadlines were looming as usual. – Gary F Jan 31 '14 at 09:25

1 Answers1

1

I think that the main issue that was causing it to "work" is that you were not setting errorMessage in the maxNumber extender, so it was not being cleared inappropriately:

function validate(newValue){
    target.hasError(parseInt(newValue) > parseInt(maxValue) ? true : false);
    target.hasError(parseInt(newValue) > parseInt(maxValue) ? "MaxVal" : "");
}
RP Niemeyer
  • 114,592
  • 18
  • 291
  • 211
  • Thanks, yep that was a cut and paste error. I guess though I still shouldn't be doing it like this as I am twice setting the same sub-observable once in the minValue check and once in the maxValue check? – Gary F May 21 '13 at 15:45
  • Yes, with the original sample that you had (with the typo fixed) they will potentially make conflicting updates to the same observable. – RP Niemeyer May 21 '13 at 16:58