【问题标题】:Unique value validation with Knockout-Validation plugin使用 Knockout-Validation 插件进行唯一值验证
【发布时间】:2013-03-31 03:02:46
【问题描述】:

我正在使用带有 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());
    })); 
}

我有一个问题。由于正在编辑的Locationlocations observableArray“分离”(参见Location.edit 方法),当我在分离的Location 中更改name 时,该值不会在names 中更新计算数组。因此,当验证规则将其与 names 数组进行比较时,它将始终返回有效状态 true,因为计数器永远只会是 1 或 0。(请参阅下面的淘汰验证算法)

unique 验证规则的选项参数中,我可以传入externalValue 的属性。如果此值未定义,则它将检查匹配名称的计数是否大于或等于 1 而不是 2。这适用于用户更改名称、转到另一个字段然后返回的情况除外到名称,并希望将其更改回原始值。该规则只是看到该值已经存在于names 数组中,并返回一个有效的 false 状态。

这是来自 knockout.validation.js 的处理 unique 规则的算法...

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

我曾考虑使用它作为基础来创建自定义验证规则,但是当用户想要返回原始值时,我一直卡在如何处理这种情况。

感谢所有帮助。

【问题讨论】:

    标签: javascript knockout.js knockout-validation


    【解决方案1】:

    一种可能的解决方案是在唯一验证器中不包括 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.

    【讨论】:

    • 是的,但是我可以通过调用 self.selectedLocationForEditing(new Location({}, self.types, self.namesExceptCurrent(''))); 来处理新项目。这是一个优雅、简单的解决方案 - 谢谢 nemesv!
    猜你喜欢
    • 2015-11-23
    • 1970-01-01
    • 2018-07-08
    • 2011-12-26
    • 2013-04-20
    • 2014-09-08
    • 2017-02-04
    • 2022-01-12
    • 2014-05-24
    相关资源
    最近更新 更多