1
votes

I am using knockoutjs along with knockoutjs validation plugin to validate my view model. Here is my javascript code

// enable validation
ko.validation.init();

// View model
function AppViewModel() {

    this.Canceled = ko.observable(false);

    this.Name = ko.observable("").extend({

        //custom validation
        validation: {
            validator: function (val, params) {

                //alert to show when validation is triggered
                alert("validation function was called");

                //change validation rule depending on whether cancel button was clicked
               if(params.Canceled == true)
                   return true;
                else
                   return false;

            },
            message: 'This field is required',
            params: {Canceled:this.Canceled()}
        }
    });


    this.errors = ko.validation.group(this);

    //function triggered on submit which checks for validation
    this.submit = function() {
        if(this.errors().length != 0)
            this.errors.showAllMessages();
        else
            alert("no errors detected");
    };

    //function to cancel validation rules
    this.cancelValidation = function() {
        this.Canceled(true);
    };
}

// Activate knockout.js
ko.applyBindings(new AppViewModel());​

and here is my HTML

Name: <input type="text" data-bind="value: Name"/><br/><br/>
<button data-bind="click: submit">submit</button> <button data-bind="click: cancelValidation">Cancel validation</button>​

What I am trying to do is to change the validation rules at runtime if the "Cancel validation" button is clicked. To do this, I am using a custom validation function along with a ko.observable variable called "Canceled". Depending on the value of "Canceled" my validator function returns true or false. The problem I am having is that the validation function runs only once when the page loads. The function is not being rerun when the value of "Canceled" changes. Is this normal behavior? Is there a way for me to rerun the validation function for the current model when I change the value of "Canceled"?

Here is a fiddle to try out the code. I have added a alert inside the validation function to show that it runs only once on page load.

http://jsfiddle.net/eewJe/

2

2 Answers

1
votes

You should pass the observable not the value into the options. Change

if(params.Canceled == true)

to

if(params.Canceled() == true)

and pass in the observable. Change

params: {Canceled:this.Canceled()}

to

params: {Canceled:this.Canceled}

Here's the updated fiddle: http://jsfiddle.net/nEPNC/

0
votes

Never mind, I was able to solve it on my own. For anyone stumbling across this question, here is my updated Javascript

// enable validation
ko.validation.init();


// View model
function AppViewModel() {

    var self = this;

    this.Canceled = ko.observable(false);

    this.Name = ko.observable("").extend({

        //custom validation
        validation: {
            validator: function (val,para) {

                //alert to show when validation is triggered
                alert("validation function was called");

                //change validation rule depending on whether cancel button was clicked
               if(self.Canceled() == true)
                   return true;
                else
                   return false;

            },
            message: 'This field is required'
        }
    });


    this.errors = ko.validation.group(this);

    //function triggered on submit which checks for validation
    this.submit = function() {
        if(this.errors().length != 0)
            this.errors.showAllMessages();
        else
            alert("no errors detected");
    };

    //function to cancel validation rules
    this.cancelValidation = function() {
        this.Canceled(true);
    };
}

// Activate knockout.js
ko.applyBindings(new AppViewModel());​

I changed my validator function to check the value of self.Canceled() directly instead of passing Canceled as a parameter as I was doing before using the "params:" property of the validator. Everything works fine now. Here is an updated fiddle

http://jsfiddle.net/HtYCw/

I'd still be interested in comments if anyone has a better way to do it.