KnockoutJS : Validate model's property only if

2019-07-29 17:55发布

问题:

I have model in a page that is bound to several controls. Based on some condition some of these controls will be visible or invisible. And on the final submit I should only validate those which are visible.

The following is a sample code to explain my requirement

<script src="knockout-3.4.0.js" type="text/javascript"></script>
    <input type="checkbox" data-bind="checked:requireAge"  >Age Required</input><br />
    Name : <input data-bind="value:Name" /><br />
    <div data-bind="visible:requireAge">
        Age: <input data-bind="value:Age,visible:requireAge" />
    </div>

    <button type="button" onclick="validateModel();">Validate</button>
    <script type="text/javascript">
        var viewModel = { Name: ko.observable(), Age: ko.observable(),requireAge:ko.observable(false) };
        ko.applyBindings(viewModel);
        function validateModel() {
            //validate visible properties and throw a common message that all visible fields should be filled
        }
    </script>

回答1:

My suggestion is to use the knockout-validation library (you made no mention of it in your question so I assume you're not using it already) It ties in seamlessly with knockout and makes validation far more convenient. I've used it extensively over the past year and its make my life a whole lot easier. No need to create computeds to keep track of whether an observable contains a valid value or not. You can find the knockout-validation library on github.

In your case you can simply do the following:

var viewModel = function(){ 
  var self = this;
  self.name = ko.observable();      
  self.requireAge = ko.observable(false);
  self.age = ko.observable().extend({ 
      required: {  
        onlyIf: function() { return self.requireAge(); } 
    } 
  });
};

Validation error messages are inserted automatically below the element the observable is bound to. You can also create your own validation rules but there are many that work straight out the box including the one demonstrated above. You can even use some data attributes for some rules. This is probably the best way to go about validation in conjunction with knockout.



回答2:

Based on some condition some of these controls will be visible or invisible.

It would be better if these conditions are contained in the model. And validation method too.

See snippet:

var viewModel = function() {
	this.Name = ko.observable("");
	this.Age = ko.observable("");
	this.requireAge = ko.observable(false);
	this.isValid = ko.computed(function() {
		if (ko.unwrap(this.Name).length === 0) return false;
		if (ko.unwrap(this.requireAge) &&
			ko.unwrap(this.Age).length === 0) return false;
		return true;
	}, this);
};

window.onload = function() {
	ko.applyBindings(new viewModel());
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<input type="checkbox" data-bind="checked:requireAge"  >Age Required</input><br />
Name : <input data-bind="value:Name" /><br />
<div data-bind="visible:requireAge">
    Age: <input data-bind="value:Age,visible:requireAge" />
</div>

<div>is valid: <span data-bind="text: isValid"></span></div>