使用敲除验证确保数组中的值是唯一的

Using knockout validation to ensure values in an array are unique

我的html代码:

<button  data-bind="click: addmyEvent">
Add New Event</button><p />
<div class="row" data-bind="foreach: myevents">
 <input type="text" data-bind="value: name" />
<button  data-bind="click: $root.addProperty">Add Property</button><p />
<div data-bind="foreach: properties">
<input type="text" data-bind="value: name" />
<button data-bind='click: addOptionValue'>Add Option </button>
        <div data-bind="foreach: optionvalues">
          <div class="form-inline">
            <input type="text" data-bind="value: optionvalue" />
          </div>
        </div>
</div>
</div>
<pre data-bind="text: JSON.stringify(ko.toJS($root), null, 2)"></pre>

我的javascript代码:

function myEvent(data){
    var self = this
    self.name=ko.observable(data.name);
    self.properties = ko.observableArray(data.propertydetails);
}

 function Property(data) {
     var self = this
     self.name=ko.observable(data.name);
     self.optionvalues = ko.observableArray(data.optionvalue);
     self.addOptionValue = function (properties) {
         properties.optionvalues.push({ optionvalue: "" });
     }
 }
 var myViewModel = function () {
      var self = this
            self.myevents = ko.observableArray([]);  

    self.addmyEvent = function () {
        self.myevents.push(new myEvent({name:"", properties: ko.observableArray() }));
    }
    self.addProperty = function (ev) {
        ev.properties.push(new Property({name:"", optionvalues: ko.observableArray()}));
    };
}
ko.applyBindings(new myViewModel());

Jsfiddle : https://jsfiddle.net/o6juohxL/9/ 1

我想使用敲除验证并确保..

我在用户贡献的规则中找到了 isUnique 规则 here 但我无法弄清楚如何使用它。

您找到的 isUnique 贡献应该适用于您的用例。我将尝试解释验证器的工作原理,以便您可以为所有用例实施它。

ko.validation 的基础知识:

  1. 首先,您必须确保 ko.validation 脚本已加载并使用自定义规则进行了扩展。
  2. 使用 .extend( /* options */ )
  3. 扩展需要验证的可观察对象

现在,我们可以看看 isUnique 实现。在文档中,您可以看到您需要提供数组/ko.observableArrayObject 以及 array 属性。让我们保持简单并使用第一个。

function myEvent(data) {
  var self = this;
  var eventNames = ko.observableArray([]);

  self.name = ko.observable(data.name).extend({
    required: true,
    isUnique: eventNames
  });
};

如果您在自定义规则中放置一个断点,您将能够检查规则是否正确运行。但它将使用一个空数组来检查唯一性。让我们解决这个问题。

A myEvent 实例对其他事件的名称一无所知。这组事件存在于 myViewModel 中。此外,它是一个可观察的对象数组,而不是事件名称。我们将创建一个新的 computed 变量来创建事件名称数组,并将引用传递给我们的 myEvent 构造函数:

// Create a computed array of names
var myEventNames = ko.computed(function() {
  return self.myevents().map(function(event) { return event.name(); });
});

// When creating a new event, give it access to this array
self.addmyEvent = function() {
  self.myevents.push(new myEvent({
    name: "",
    properties: ko.observableArray()
  }, myEventNames));
};

现在,我们可以回到 myEvent 并从构造函数中删除 eventNames 声明。现在是myViewModel.

传递的参数
function myEvent(data, eventNames) {
  var self = this;
  self.name = ko.observable(data.name).extend({
    required: true,
    isUnique: eventNames
  });

  // Other code ...
};

这是否使您能够自己找出其他实现方式?让我知道你的想法。

这是一个 fiddle 我举的例子:https://jsfiddle.net/ute3uem6/

编辑:如果你不想用计算乱丢你的视图模型,你可以使用 isUnique 规则中的 predicate 功能:

它是这样工作的:如果你提供了一个方法来告诉isUnique 如何将当前值与数组中的值进行比较,你不需要将 myevents observable 映射到字符串数组。它做同样的事情,但使用不同的方法。我想你选择哪种方式是个人喜好。

isUnique: {
    array: events,
    predicate: function(currentEvent, currentValue) {
      return currentEvent.name() === currentValue;
    }
}