在knockout.js中创建脏标志绑定

在knockout.js中创建脏标志绑定,knockout.js,Knockout.js,我正在尝试创建一个绑定处理程序,它允许我跟踪绑定中使用的任何值是否已更改: <div id="container1" data-bind="dirty: $root.container1Dirty"> <span data-bind="visible: $root.container1Dirty">*</span> <label> Text 1 <input data-bind="value:

我正在尝试创建一个绑定处理程序,它允许我跟踪绑定中使用的任何值是否已更改:

<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.applybindingstosubjects
能够订阅该容器中所有绑定中使用的可观察对象。然而,情况似乎并非如此;看


有没有其他方法可以做到这一点?或者最好为每个容器创建一个ViewModel,然后使用?

不确定这是否是最好的解决方案,但您可以将脏标志包装到一个“基类”中,并保持视图模型之间的所有逻辑共享。例如:

<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());  

var BaseViewModel=函数(saveUrl,数据){
var-self;
this.isDirty=ko.可观察(假);
this.save=函数(){
var jsData=ko.toJS(数据);
警报(“保存:”+jsData.textBox);
};
};
var pageViewModel=函数(){
var self=这个;
this.textBox=ko.可观察(“”);
extend(self,newbaseviewmodel('url for save',{textBox:self.textBox}));
}
应用绑定(新的pageViewModel());

如果您不想指定事件,只需对所有观察对象应用“脏”检查,您可以尝试以下操作:

目前,我正在手动提供所有要跟踪的观察对象:

<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());  
<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>


这并不是我真正希望的解决方案,因为我现在必须手动提供我想要跟踪的所有观察值,而不是自动查找所有使用的观察值。因此,我仍然希望找到更好的解决方案。

@michaelpapworth我已经知道如何跟踪ViewModels的更改,但在这种情况下,我希望订阅特定元素中使用的所有观察值。这对我没有帮助。我希望能够自动检测元素内的更改,而不必向所有输入元素添加类似于
keyup:isDirty
的内容。我更新了答案,以继续使用相同的模式,但从输入中删除事件……这样,您仍然需要手动订阅所有要观看的观测值。但我希望通过应用自定义绑定,自动监视/订阅特定容器(元素)中使用的所有可观察对象。
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')
});