有没有办法创建一个ko.computed字段,通知发生了数组元素发生的变化?
我的第一个想法是使用observableArray,但它不起作用,因为
An observableArray tracks which objects are in the array, not the state of those objects
不过,我发布这段代码来说明我正在尝试做什么。
HTML:
<div data-bind="foreach:arr">
<input type="text" value="" data-bind="value: a" />
</div>
<div data-bind="foreach:arr">
<p>
Field "a" is changed: <span data-bind="text: aChanged()? 'true': 'false'"></span>
</p>
</div>
<p>
Some "a" field from the array is changed: <span data-bind="text: someAChanged()? 'true': 'false'"></span>
</p>
JavaScript的:
function AppViewModel() {
this.arr = ko.observableArray([new A(), new A()]);
this.someAChanged = ko.computed(function () {
var ch = false;
var arr = this.arr();
for (var i = 0; i < arr.length; i ++) {
if (arr[i].aChanged()) {
ch = true;
break;
}
return ch;
}
}, this);
}
function A() {
this.a = ko.observable(1);
this.aChanged = ko.computed(function() {
return this.a() != 1;
}, this);
}
ko.applyBindings(new AppViewModel());
由于我没有权利回答我自己的问题,我在这里发表我的想法。 我决定使用“订阅”功能。我的解决方案是添加一个“父”链接到数组的元素。每当一个可观察字段发生变化时,依赖于其子节点的父字段也会发生变化:
function Child () {
this._parent = null;
this.observableField = ko.observable("");
this.observableField.subscribe(function (newVal) {
if (newVal... && this._parent) {
this._parent.anotherObservableField(...);
}
});
}
Child.prototype._setParent(parent) {...}
答案 0 :(得分:2)
您需要确保someAChanged
computed正在为数组中的每个项目注册依赖项。
这样的事情应该有效:
function AppViewModel() {
this.arr = ko.observableArray([new A(), new A()]);
this.someAChanged = ko.computed(function () {
var ch = false;
var changedItem = null;
var arr = this.arr();
ko.utils.arrayForEach(this.arr(), function(item){
var changed = item.changed(); //someAChanged registers a change subscription here
if(changed && !ch){
ch = true;
changedItem = item;
}
});
return changedItem;
}, this);
};
基本上,这会为您阵列中的每个项目注册“更改”订阅。您之前的代码在找到的第一个代码处停止,这意味着您的数组中没有其他项目添加了“更改”订阅。循环遍历数组中的每个项目并使其成为someAChanged
计算的依赖项,如果您的数组中有很多项目,则会很昂贵。
上面的代码也将返回更改的第一个项目。我以为这是你想要的。如果没有,那么重新处理它以返回一组已更改的项目将非常容易。
答案 1 :(得分:0)
我在创建时设置了一个简单的初始值,并检查了我想要结帐的任何字段,如果在计算的observable上更改了这样的话:
var initPrice = line.Price;
var initCurrency = line.IdCurrency;
self.isModified = ko.computed(function() {
return self.Price() !== initPrice || self.IdCurrency() !== initCurrency;
});
答案 2 :(得分:0)
我想你几乎就在那里。你的html很好,你的淘汰赛,但你的someAChanged计算功能不正常。如果A已经改变了,你将ch变量设置为true并且跳出for循环但是你实际上从未返回true。实际上你根本不需要ch变量。
function AppViewModel() {
this.arr = ko.observableArray([new A(), new A()]);
this.someAChanged = ko.computed(function () {
var arr = this.arr();
for (var i = 0; i < arr.length; i ++) {
if (arr[i]().aChanged()) {
return true;
}
}
return false;
}, this);
}