我正在尝试创建一个绑定处理程序,它允许我跟踪绑定中使用的任何值是否已更改:
<div id="container1" data-bind="dirty: $root.container1Dirty">
<span data-bind="visible: $root.container1Dirty">*</span>
<label>
Text 1
<input data-bind="value: $root.text1" />
</label>
</div>
到目前为止,我尝试了以下内容:
ko.bindingHandlers.dirty = {
init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var counter = 0;
var dirtyObservable = valueAccessor();
var appliedBindings = false;
var computed = ko.computed(function() {
if (!appliedBindings) {
// I was hoping this would subscribe all the used observables
ko.applyBindingsToDescendants(bindingContext, element);
appliedBindings = true;
}
// make sure subscribe is triggered by returning a new value
return counter++;
});
computed.subscribe(function() {
dirtyObservable(true);
});
return { controlsDescendantBindings: true };
}
};
我希望ko.applyBindingsToDescendants
订阅该容器内所有绑定中使用的observable。然而,情况似乎并非如此;见http://jsfiddle.net/F3uMr/1/。
还有另一种方法可以达到这个目的吗?或者为每个容器创建一个ViewModel然后使用dirty flag?
会更好答案 0 :(得分:1)
不确定这是否是最佳解决方案,但您可以将脏标志包装到“基类”中并保持视图模型之间共享的所有逻辑。例如:
<强> Fiddle is here 强>
<input type='text' data-bind="value: textBox, event: { keyup: isDirty }">
<input type='button' value='click me if you can' data-bind="click: save, ,enable: isDirty">
var BaseViewModel = function (saveUrl, data) {
var self;
this.isDirty = ko.observable(false);
this.save = function(){
var jsData = ko.toJS(data);
alert('save: ' + jsData.textBox);
};
};
var pageViewModel = function(){
var self = this;
this.textBox = ko.observable('');
ko.utils.extend(self, new BaseViewModel('url for save', {textBox: self.textBox}));
}
ko.applyBindings(new pageViewModel());
如果您不想指定事件并且只对所有可观察对象应用“脏”检查,您可以尝试以下方法: Fiddle
答案 1 :(得分:1)
现在我手动提供所有可观察的跟踪:
<div id="container1" data-bind="
dirty: {
flag: 'container1Dirty',
target: [$root.text1]
}">
<span data-bind="visible: container1Dirty">*</span>
<label>
Text 1
<input data-bind="value: $root.text1" />
</label>
</div>
使用以下绑定处理程序:
ko.bindingHandlers.dirty = {
init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var data = valueAccessor();
var dirtyObservable = ko.observable(false);
var orgValue = ko.toJSON(data.target);
var extraBinding = {};
extraBinding[data.flag || 'dirty'] = dirtyObservable;
var innerBindingContext = bindingContext.extend(extraBinding);
ko.applyBindingsToDescendants(innerBindingContext, element);
var dirty = ko.computed(function() {
return orgValue !== ko.toJSON(data.target);
});
dirty.subscribe(function(isDirty) {
dirtyObservable(isDirty);
});
return { controlsDescendantBindings: true };
}
};
ko.applyBindings({
text1: ko.observable('text1'),
text2: ko.observable('text2')
});
这不是我希望的解决方案,因为我现在必须手动提供我想跟踪的所有可观察对象,而不是自动查找所有使用过的可观察对象。所以我仍然愿意接受更好的解决方案。