我正在寻找一个自定义绑定的例子(如果可能的话,jsfiddle)多年前我们曾经称之为“复合组件”。我真的不希望有人为我编写代码。在我投入大量时间之前,我只想查看几个样本,但我找不到任何样本。大多数自定义绑定示例仅限于一种方式。只是询问你是否知道类似的样本......
大多数HTML / CSS都是由设计团队提供给我的,所以布局并不总是我的选择。在这种情况下,日期,电话号码和社会保障输入都是使用共同的“主题”创建的。那个主题是在div中有三个独立的元素。例如,日期有一个月,一个是一天,一个是一年。 (我不认为我们不需要将它们与旋转器一起复杂化)。预计会有验证和最大/最小输入限制。
我按如下方式创建了一个对象
var SplitDate = function (date) {
var self = this;
self.month = ko.observable();
self.day = ko.observable();
self.year = ko.observable();
var momentDate = moment(date);
if (momentDate.isValid()) {
self.month(momentDate.month() + 1);
self.day(momentDate.day());
self.year(momentDate.year());
}
}
在我的viewmodel中,我尝试了两种
self.dateOfBirth = new SplitDate(myDate);
和
self.dateOfBirth = ko.observable(new SplitDate(myDate));
但这些都没有使用标准值绑定(例如
)正确绑定data-binding = "value: dateOfBirth.day" or data-binding = "value: dateOfBirth().day"
所以我假设我需要一个自定义绑定。我不确定什么是最好的方法,如果所有这些都需要是可观察的。我们正在使用Knockout验证,所以我也希望我能为isDalid()添加一个函数给SplitDate。
所以我的问题是,在我花了几个小时摸索这个之前,有没有人有一个好榜样?
答案 0 :(得分:1)
您的SplitDate
对象将月,日,年作为单独的组件进行跟踪。听起来像你在尝试使用完整日期设置它们并且遇到麻烦。我怀疑你做的是这样的事情:
self.dateOfBirth = new SplitDate(newDate);
这不起作用,您的视图绑定到之前SplitDate
中的可观察对象。您需要做的是更新日期组件。
然而,我认为你正在犯这个错误。拆分日期应该是完整日期的包装,而不仅仅是某些日期组件。您只需要为要支持的不同字段提供访问者。在淘汰赛中,您需要一个可观察的完整日期,然后计算不同领域的观察值。
function SplitDate(date) {
var _date = ko.observable(); // the backing field
setDate(date);
// we can intercept set attempts to validate
this.date = ko.computed({ read: _date, write: setDate });
this.year = ko.computed({ read: makeGetter('year'), write: makeSetter('year') });
// we need to special case months to offset to be 1-based
this.month = ko.computed({ read: getMonth, write: setMonth });
// the date is the day of the month, day is day of the week
this.day = ko.computed({ read: makeGetter('date'), write: makeSetter('date') });
function setDate(date) {
var momentDate = moment(date);
if (momentDate.isValid()) _date(momentDate);
}
function makeGetter(field) {
var getter = moment.fn[field];
return function () {
var date = _date();
if (date) return getter.call(date);
};
}
function makeSetter(field) {
var setter = moment.fn[field];
return function (value) {
var date = _date();
if (date) {
setter.call(date, value);
// we modified the underlying value, notify
_date.valueHasMutated();
}
};
}
// we need to offset months
function getMonth() { // 1-12
var date = _date();
if (date) return date.month() + 1;
}
function setMonth(month) { // 1-12
var date = _date();
if (date) {
date.month(month - 1);
_date.valueHasMutated();
}
}
}
使用此方法,可以将日期的任何组成部分的值更改为常规可观察值。
self.dateOfBirth = new SplitDate(date);
self.dateOfBirth.month(8); // August
self.dateOfBirth.date(newDate);
您应该能够单独绑定到这些字段,并且字段上的任何更新都会像您期望的那样更新基础日期。
<input type="text" data-bind="value: dateOfBirth.date"/>
<input type="text" data-bind="value: dateOfBirth.year"/>
<input type="text" data-bind="value: dateOfBirth.month"/>
<input type="text" data-bind="value: dateOfBirth.day"/>