2012-11-28 24 views
5

我正在试验并查看是否有任何巧妙的解决方案来创建可以抽象为整洁和重用的自定义验证器。针对某个条件验证observableArray

在下面的jsfiddle中,我只是放在一起存储和测量数组(简单的值和日期)的简单父模型。在这个例子中,我提出了两个要求。

  1. 每个测量都有提供的两个字段,或者都不必提供。
  2. 在父数组中必须至少有一个有效(符合以前的条件)测量 。

    理想情况下,我希望验证逻辑的定义是有效的,存储在Measurement对象内,如下所示。但是,我非常反感的是我在atLeastOne()的父模型中必须执行的“动手”验证。

敲除验证会自动验证数字和日期的个别字段但是,我必须介入并执行对数组规则的验证。

问题:是允许我设置KO验证检查数组为此所要求的条件,同时还具有HasValues方法仍然驻留在计量模型的任何方法???也就是说,我想将搜索“至少一个”的概念抽象为某种可以为我处理工作的自定义验证程序,然后告诉验证程序“嘿,这是我希望您用来验证的函数数组中的每个项目“。

在此先感谢!

function Model(data) 
    { 
     var self = this; 
     self.Measurements = ko.observableArray(); 

     for(var i = 0; i < data.length; i++) 
      self.Measurements.push(new Measurement(data[i])); 

     function hasAtLeastOne(){ 
      var atLeastOne = false; 
      $.each(self.Measurements(), function(i, item) { 
       if (item.HasValues()) { 
        atLeastOne = true; 
        return; 
       } 
      }); 
      return atLeastOne; 
     } 

     self.Save = function() {    
      if (self.canSave() && atLeastOne()) 
       alert('save'); 
      else 
       alert('arg!'); 
     }; 

     self.errors = ko.validation.group(self); 
     self.canSave = ko.computed(function() { 
      return self.errors().length == 0; 
     }); 
    } 

    function Measurement(data) 
    { 
     var self = this; 
     self.Value = ko.observable(data.val); 
     self.Date = ko.observable(data.date); 

     self.Value.extend({ required: { onlyIf: isRequired }, number: true }); 
     self.Date.extend({ required: { onlyIf: isRequired }, date: true }); 

     self.HasValues = function() { 
      return ko.utils.isNotNullUndefOrEmpty(self.Value()) && 
        self.Date() && self.Date().length > 0; 
     }; 

     function isRequired() { 
      return ko.utils.isNotNullUndefOrEmpty(self.Value()) || 
        (self.Date() && self.Date().length > 0); 
     } 
    } 

    ko.utils.isNotNullUndefOrEmpty = function (value) { 
     return (typeof value === 'string' && value.length > 0) || 
       (typeof value !== 'string' && value); 
    }; 

这里是有我的例子中发挥的jsfiddle: http://jsfiddle.net/cACZ9/

回答

7

我一直在围绕库源碴,看看我能发现的东西,将是一个可行的选择。这是我到目前为止发现的。

两种不同的选择都与(当然)优点/缺点:

使用定制的校验:

ko.validation.rules['AtLeastOne'] = { 
     validator: function (array, predicate) { 
      var self = this; 
      self.predicate = predicate; 
      return ko.utils.arrayFirst(array, function (item) { 
       return self.predicate.call(item); 
      }) != null; 
     }, 
     message: 'The array must contain at least one valid element.' 
    }; 


    function Modal() { 
    var self = this; 
    self.Measurements = ko.observableArray().extend({ AtLeastOne: function() { 
     return this && this.HasValues(); 
    } 

    ...//refer to OP 
    ... 
    ... 

    self.Save() = function() { 
     if (self.errors().length == 0) 
      alert('Everything is valid, we can save!'); 
     else if (!self.Measurements.isValid()) 
      alert('You must have at least one valid item in the pot!'); 
    }; 
    }); 

这种方法非常需要验证了程序员的手,是非常可重复使用。但是,我注意到一个潜在的问题是它会在每次存储在数组中的任何值(对象或其他)发生变化时调用自定义验证规则。对大多数人来说可能不是问题。

使用验证器厂:

var KoValidationFactory = { 
     AtLeastOne: function (measurements, validator) { 
      return function() { 
       var self = this; 
       self.validator = validator; 
       return ko.utils.arrayFirst(measurements, function (measurement) { 
          return self.validator.call(measurement); 
         }) != null; 
      }; 
     } 

    }; 

    function Modal() { 
     var self = this; 
     self.Measurements = ko.observableArray(); 

    ...//refer to OP 
    ... 
    ... 

     self.Save = function() { 
      var atLeastOneArrayValidator = KoValidationFactory.AtLeastOne(self.Measurements(), function() { 
       return this && this.HasValues(); 
     }); 
      var arrayWasValid = atLeastOneArrayValidator(); 
      if (arrayWasValid && self.errors() == 0) 
      alert('everything is good, we can save'); 
      else if (!arrayWasValid) 
      alert('You must have at least one item in the pot!'); 
     }; 
    } 

这种方法可以确保你只能验证整个数组,当你明确地选择这样做。缺点是你有更多的动手工作,并没有充分利用淘汰赛验证库。您必须专门验证数组和任何其他所有可能使用这种方法的可观察性,如果这些方法中有很多可能会变得混乱。

我鼓励对这些方法进行编辑和建议。