我正在尝试使用KnockoutJS使用以下代码编写基本表单:
var Form = function() {
var self = this;
self.name = {
value: ko.observable(""),
isValid: ko.computed(function () {
return self.name.value().length > 0;
}),
},
self.email = {
value: ko.observable(""),
isValid: ko.computed(function () {
return false;
})
},
self.message = {
value: ko.observable(""),
isValid: ko.computed(function () {
return false;
})
},
self.isValid = ko.computed(function () {
return self.name.isValid && self.email.isValid && self.message.isValid;
})
};
但是,当我尝试运行此代码时,出现以下错误:Unable to get property 'value' of undefined or null reference
。对我来说,这看起来像是一个范围问题,但我对Knockout不够熟悉,无法理解为什么会发生这种情况。没有Knockout我似乎能够使这个代码工作(用isValid的值和函数替换所有的observable),但我希望实时更新这些值。我可以总是将验证功能分离到顶级功能,但这似乎是不正确的方法。每个表单字段都有一个值,并且它有自己唯一的验证,因此将每个表单字段作为两个属性的自己的对象是有意义的。
感谢任何帮助或指导。
答案 0 :(得分:2)
这个
self.name = {
value: ko.observable(""),
isValid: ko.computed(function () {
return self.name.value().length > 0;
}),
},
不起作用,因为内部函数(计算的回调)引用self.name
,甚至还没有完全定义。由于立即调用计算机,您会看到错误。
你可以使用deferEvaluation
option延迟评估isValid
计算,直到实际请求其值为止:
self.name = {
value: ko.observable(""),
isValid: ko.computed({
read: function () { return self.name.value().length > 0; },
deferEvaluation: true
}),
},
这样可行,但它也很快就会变得重复和笨拙。
作为替代方案,您可以使用Knockout extenders以抽象/分离的方式创建可观察的可验证值。
ko.extenders.validator = function (target, validationCallback) {
// create an isValid property on the target observable,
// immediately calculate validity of its current value
target.isValid = ko.observable(validationCallback(target()));
// subscribe to future changes
target.subscribe(function (newValue) {
target.isValid(validationCallback(newValue));
});
// return target observable for chaining
return target;
};
现在定义了这个扩展器,你需要做的就是创建回调函数,验证一个值并返回true或false。
var Form = function () {
var self = this;
self.name = ko.observable("").extend({
validator: function (value) { return value.length > 0; }
});
self.email = ko.observable("").extend({
validator: function (value) { return true; }
});
self.message = ko.observable("").extend({
validator: function (value) { return true; }
});
self.isValid = ko.computed(function () {
var overallValid = true;
ko.utils.objectForEach(self, function (key, value) {
if (value.hasOwnProperty("isValid")) {
overallValid = overallValid && value.isValid();
}
});
return overallValid;
});
};
现在,进一步分离验证功能变得非常简单:
var validators = {
email: function (value) { return /* email check here */; },
minLen: function (minLen) {
return function (value) { return value.length >= minLen; }
},
maxLen: function (maxLen) {
return function (value) { return value.length <= maxLen; }
},
minmaxLen: function (minLen, maxLen) {
return function (value) { return value.length >= minLen && value.length <= maxLen; }
},
matches: function (regex) {
return function (value) { return regex.test(value); }
}
}
和
self.name = ko.observable("").extend({ validator: validators.minLen(1) });
self.age = ko.observable("").extend({ validator: validators.matches(/^\d+$/) });
你会发现somebody already did all of this(以及更多)。
答案 1 :(得分:0)
最好为每个对象创建单独的函数:
var Form = function() {
var self = this;
self.name = new NameFormField();
}
var NameFormField = function() {
var self = this;
self.value = ko.observable("");
self.isValid = ko.computed(function () {
//not sure why you are checking length here
return self.value().length > 0;
});
}
你能让它发挥作用的另一种方法是:
var Form = function() {
var self = this;
self.name = {
value: ko.observable("")
};
self.name.isValid = ko.computed(function () {
//not sure why you are checking length here
return self.name.value().length > 0;
});