[英]Knockout computed and input validation
我是淘汰赛的新手,我想弄清楚如何将两件我理解的东西放在一起。
我需要:
例:
startTime
以秒为单位的duration
以及从startTime + duration
计算的stopTime
startTime
无法更改 duration
和stopTime
与输入字段相关联 stopTime
并以HH:MM:SS
格式输入 stopTime
,则应计算并自动更新duration
duration
,则应计算并自动更新stopTime
我可以让它们互相更新(假设Sec2HMS
和HMS2Sec
在别处定义,并在HH:MM:SS
和秒之间转换):
this.startTime = 120; // Start at 120 seconds
this.duration = ko.observable(0);
// This dependency works by itself.
this.stopTimeFormatted = ko.computed({
read: function () {
return Sec2HMS(this.startTime + parseInt(this.duration()), true);
},
write: function (value) {
var stopTimeSeconds = HMS2Sec(value);
if (!isNaN(stopTimeSeconds)) {
this.duration(stopTimeSeconds - this.startTime);
} else {
this.duration(0);
}
},
owner: this
});
或者,我可以使用extenders
或fn
验证输入,如敲除文档中所示:
ko.subscribable.fn.HMSValidate = function (errorMessage) {
//add some sub-observables to our observable
var observable = this;
observable.hasError = ko.observable();
observable.errorMessage = ko.observable();
function validate(newValue) {
var isInvalid = isNaN(HMS2Sec(newValue));
observable.hasError(isInvalid ? true : false);
observable.errorMessage(isInvalid ? errorMessage : null);
}
//initial validation
validate(observable());
//validate whenever the value changes
observable.subscribe(validate);
//return the original observable
return observable;
};
this.startTime = 120; // Start at 120 seconds
this.duration = ko.observable(0);
this.stopTimeHMS = ko.observable("00:00:00").HMSValidate("HH:MM:SS please");
但是我如何让他们一起工作呢? 如果我将HMSValidate
添加到第一个块中的计算中它不起作用,因为当HMSValidate
的validate
函数获得它已经被更改的值时。
我通过添加另一个observable使其在第一个块中工作,该observable跟踪传递给计算器的“原始”值,然后添加另一个使用该值的计算器来判断它是否是错误状态,但是没有感觉非常优雅。
有没有更好的办法?
经过一个星期的回收问题后,我回到了这个问题,我没有解决方法(代码清理时间!),这就是我所拥有的。
我最终提出了我在问题的最后提到的想法,但是将其封装在fn本身中。
ko.subscribable.fn.hmsValidate = function (errorMessage) {
var origObservable = this;
var rawValue = ko.observable(origObservable()); // Used for error checking without changing our main observable.
if (!origObservable.hmsFormatValidator) {
// Handy place to store the validator observable
origObservable.hmsFormatValidator = ko.computed({
read: function () {
// Something else could have updated our observable, so keep our rawValue in sync.
rawValue(origObservable());
return origObservable();
},
write: function (newValue) {
rawValue(newValue);
if (newValue != origObservable() && !isNaN(HMS2Sec(newValue))) {
origObservable(newValue);
}
}
});
origObservable.hmsFormatValidator.hasError = ko.computed(function () {
return isNaN(HMS2Sec(rawValue()));
}, this);
origObservable.hmsFormatValidator.errorMessage = ko.computed(function () {
return errorMessage;
}, this);
}
return origObservable.hmsFormatValidator;
};
这样做会创建另一个计算的observable,它作为原始observable的前置/过滤器。 该observable有一些其他的子可观察对象, hasError
和errorMessage
,附加到它的错误状态。 rawValue
会跟踪输入的值,以便我们可以检测它是否是一个好的值。 这可以处理我的一半要求。
至于使两个值相互依赖,我问题中的原始代码有效。 为了验证它,我添加了hmsValidate
,如下所示:
this.stopTimeFormatted = ko.computed({
read: function () {
return Sec2HMS(this.startTime + parseInt(this.duration()), true);
},
write: function (value) {
this.duration(HMS2Sec(value) - this.startTime);
},
owner: this
}).hmsValidate("HH:MM:SS please");
在这里看到它: http : //jsfiddle.net/cygnl7/tNV5S/1/
值得注意的是, write
内部的验证不再是必要的,因为只有在正确验证的情况下,该值才会由hmsValidate
写入。
这对我来说仍然感觉有点不雅,因为我正在检查isNaN几次并且必须跟踪原始值(特别是在read()中),所以如果有人想出另一种方法来做到这一点,我都是耳朵。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.