所以我有一个自定义的敲除绑定来处理持续时间。我有一个问题,其中我的一个表单中的值可能是一个持续时间,但也可能是一个字符串或其他值。这个问题源于持续时间值表示为具有两个属性的对象,持续时间和time_unit(它本身就是一个具有2个属性的对象。如果绑定,我将各种绑定节点绑定在内部。
init: function(element, valueAccessor, allBindingsAccessor, viewModel, context) {
var allBindings = ko.toJS(allBindingsAccessor() || {}),
source = allBindings.source || [],
observable = valueAccessor(),
value = ko.toJS(ko.utils.unwrapObservable(observable)),
duration = new DurationControl({
inputNode: inputNode,
source: source,
defaultValue: value
});
//attach duration control to element and render here
ko.utils.registerEventHandler(inputNode.getDOMNode(), 'blur', function () {
var observable = valueAccessor();
if (!observable.viewModelUpdating) {
observable.viewModelUpdating = ko.observable(false);
}
if (duration.isValueValid(true)) {
observable.viewModelUpdating(true);
observable.duration(duration.getDuration());
observable.time_unit.value(duration.getTimeUnit());
observable.time_unit.id(sourceIdValueMap[duration.getTimeUnit()] || 0);
observable.viewModelUpdating(false);
}
});
}
我绑定的HTML
<!-- ko if: type() == 'string' -->
<div class="control wide">
<input type="text" data-bind="value: value" />
</div>
<!-- /ko -->
<!-- ko if: type() == 'duration' -->
<div class="control">
<input type="text" data-bind="duration: value, source: metadata.time_units" />
</div>
<!-- /ko -->
如果我执行初始绑定,其值是正确的对象格式,如此
...,
value: {
duration: '',
time_unit: {
value: '',
id: '',
}
},
...
一切都很好。但是如果我以其他格式开始使用值,例如..., value: 'nada', ...
,它会尝试访问observable.duration(和observable.time_unit。*)。
当我通过正确的设置评估值时,我将上述对象取回。如果我尝试手动将duration / time_unit属性添加为observables,我仍然只是将空字符串退出。
我如何最好地从我的init函数中更新viewmodel / bindings / etc ,以便它在初始化时表现得好像模型最初处于该状态?
答案 0 :(得分:2)
自定义绑定不是您问题的解决方案。 Knockout将绑定它在DOM中遇到的所有内容,因此无论您使用哪个类型的对象初始化,另一个将失败。我已经实现了类似的东西,在我的视图模型中可观察到的存储了多种类型的东西。&#39;对象,您将需要&#39;类型特定的&#39; UI的一部分绑定到每个。这就是我解决这个问题的方法:
删除if: type() == '<type>'
的所有实例,并将每段HTML实现为template。
现在重构决策过程。使用computed observable根据type()
决定显示哪个模板。像这样......
function ViewModel(){
var self = this;
self.type = ko.observable();
self.value = ko.observable();
self.currentValueTemplate = ko.computed(function(){
switch(self.type()) {
case 'string':
return 'stringTemplate';
case 'duration':
return 'durationTemplate';
default:
throw 'invalid type';
}
});
现在只需添加模板占位符...
<!-- ko template: { name: currentValueTemplate, data: value } -->
<!-- /ko -->
您可能希望对此进行调整以适合您的应用程序的细节,但它是一种更整洁的方法,如果您想要存储越来越多的对象类型,它将更好地扩展。