【问题标题】:Validating observableArray against a condition根据条件验证 observableArray
【发布时间】:2012-11-16 15:22:10
【问题描述】:

我正在尝试试验,看看是否有任何聪明的解决方案来创建自定义验证器,这些验证器可以被抽象出来以实现整洁和重用。

在下面的 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/

【问题讨论】:

    标签: knockout.js knockout-validation


    【解决方案1】:

    我一直在研究库源代码,看看是否能发现一些可行的选择。这是我目前发现的。

    两种不同的选择,各有利弊(当然):

    使用自定义验证器:

     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!');
           };
       }
    

    这种方法可以确保您仅在您明确选择时才验证整个数组。不利的一面是您有更多的动手工作,并且没有充分利用淘汰赛验证库。您必须专门验证数组和任何/所有其他采用这种方法的可观察对象,如果它们很多,可能会变得混乱。

    我鼓励对这些方法进行修改和提出建议。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-24
      相关资源
      最近更新 更多