我正在使用带有Knockout-Validation插件的KnockoutJS来验证表单上的字段。我在使用原生验证规则unique验证值的唯一性时遇到了问题
我使用Ryan Niemeyer的编辑器模式来允许用户编辑或创建Location。这是我的fiddle,可以完整地了解我的问题。
function Location(data, names) {
var self = this;
self.id = data.id;
self.name = ko.observable().extend({ unique: { collection: names }});
// other properties
self.errors = ko.validation.group(self);
// update method left out for brevity
}
function ViewModel() {
var self = this;
self.locations = ko.observableArray([]);
self.selectedLocation = ko.observable();
self.selectedLocationForEditing = ko.observable();
self.names = ko.computed(function(){
return ko.utils.arrayMap(self.locations(), function(item) {
return item.name();
});
});
self.edit = function(item) {
self.selectedLocation(item);
self.selectedLocationForEditing(new Location(ko.toJS(item), self.types));
};
self.cancel = function() {
self.selectedLocation(null);
self.selectedLocationForEditing(null);
};
self.update = function(item) {
var selected = self.selectedLocation(),
updated = ko.toJS(self.selectedLocationForEditing()); //get a clean copy
if(item.errors().length == 0) {
selected.update(updated);
self.cancel();
}
else
alert("Error");
};
self.locations(ko.utils.arrayMap(seedData, function(item) {
return new Location(item, self.types, self.names());
}));
}不过,我有个问题。由于正在编辑的Location是从locations observableArray“分离”的(请参阅Location.edit方法),因此当我在分离的Location中更改name时,该值不会在names计算数组中更新。因此,当验证规则将其与names数组进行比较时,它将始终返回有效状态true,因为计数器永远只是1或0。(请参阅下面的淘汰法-验证算法)
在unique验证规则的options参数中,我可以传入externalValue的属性。如果该值不是未定义的,则它将检查匹配名称的计数是否大于或等于1而不是2。除非用户更改了名称,转到另一个字段,然后返回到名称,并希望将其更改回原始值。该规则只看到该值已经存在于names数组中,并返回有效状态false。
下面是处理unique规则的knockout.validation.js算法...
function (val, options) {
var c = utils.getValue(options.collection),
external = utils.getValue(options.externalValue),
counter = 0;
if (!val || !c) { return true; }
ko.utils.arrayFilter(ko.utils.unwrapObservable(c), function (item) {
if (val === (options.valueAccessor ? options.valueAccessor(item) : item)) { counter++; }
});
// if value is external even 1 same value in collection means the value is not unique
return counter < (external !== undefined && val !== external ? 1 : 2);
}我曾考虑过使用它作为创建自定义验证规则的基础,但当用户希望返回到原始值时,我一直被困在如何处理这种情况上。
我感谢所有人的帮助。
发布于 2013-04-12 00:18:30
一种可能的解决方案是在唯一验证器中不包括当前编辑项的 name (当然,在创建新项时,您需要完整的列表)。
因此,当将位置名称更改回其原始值时,不会触发唯一检查:
self.namesExceptCurrent = function(name){
return ko.utils.arrayMap(self.locations(), function(item) {
if (item.name() !== name)
return item.name();
});
}
self.edit = function(item) {
self.selectedLocation(item);
self.selectedLocationForEditing(
new Location(ko.toJS(item),
self.types,
self.namesExceptCurrent(item.name())));
};演示JSFiddle.
https://stackoverflow.com/questions/15889129
复制相似问题