我的视图模型的属性上有一个observableArray:
self.rates = ko.observableArray([])
数组的内容显示在HTML表格中。有一个按钮可以向数组添加项目。这些是经过验证的可观测量:
self.newRate = function () {
var rate = new Rate({id: self.id});
rate.isEditing(true);
rate.isNew = true;
rate = ko.validatedObservable(rate);
self.vendor().rates.push(rate);
};
这很好用。该项目将添加到阵列中,并且视图会更新。新添加的项目旁边有一个取消链接,允许用户删除该行。
self.editRateCancel = function (item) {
if (item.isNew === true) {
self.vendor().rates.remove(item);
} else {
item.cancelEdit();
ko.utils.arrayForEach(self.unitsOfMeasure(), function (uom) {
if(item.cacheUnitOfMeasureID === uom.value) {
item.selectedUOM(uom);
}
});
}
};
对remove(item)
的调用不会删除该项目。如果我没有将项目设置为经过验证的observable,则删除成功。查看remove
函数显示传入的项(valueOrPredicate)的类型为Object, (Rate)
,但从底层数组返回的值为Object, (Function)
,因此predicate(value)
返回false,因此不会删除该项。
KnockoutJS删除功能:
ko.observableArray['fn'] = {
'remove': function (valueOrPredicate) {
var underlyingArray = this.peek();
var removedValues = [];
var predicate = typeof valueOrPredicate == "function" ? valueOrPredicate : function (value) { return value === valueOrPredicate; };
for (var i = 0; i < underlyingArray.length; i++) {
var value = underlyingArray[i];
if (predicate(value)) {
if (removedValues.length === 0) {
this.valueWillMutate();
}
removedValues.push(value);
underlyingArray.splice(i, 1);
i--;
}
}
if (removedValues.length) {
this.valueHasMutated();
}
return removedValues;
},
如何从可观察数组中删除特定的经过验证的observable?有没有可用的实用功能?
答案 0 :(得分:1)
我刚刚遇到这个问题而且我的研究引导我到这里,所以我会记下我为解决它而做的事情。
knockout中的foreach绑定允许使用$ index()访问当前元素的索引。而不是使用将对象传递给remove函数的常规机制,我传递了索引。
实施例
常用:
function ViewModel() {
var self = this;
.
.
.
removeItem(item) {
// Tries to remove matching object, fails on observables
self.myArray.remove(item);
}
}
我的解决方法:
function ViewModel() {
var self = this;
.
.
.
removeItem(index) {
// Removes 1 item at position of index
self.myArray.splice(index, 1);
}
}
在解决方法中,html看起来像这样
<div data-bind="foreach: myArray">
<p data-bind="text: somePropertyOfTheObject"></p>
// The bind call puts the index into the list of parameters of the function so it is available in the removeItems function
<input type="button" value="remove" data-bind="click: $root.removeItem.bind(null, $index())" />
</div>
最后这是我制作的小提琴。 https://jsfiddle.net/jimmypc15/yf5h0kf2/2/
答案 1 :(得分:0)
我遇到了同样的问题,这些是我尝试过的方法:
第一种方法
创建一个可观察数组,其实例为Rate
和一个计算的observable,它将每个项目从Rate返回为validatedObservable
。这种方法的问题在于,每次向数组添加或删除项时,都会重新创建所有validatedObservable
,这样做效率不高并导致奇怪的UI行为。
第二种方法
为deleted
创建一个额外的Rate
可观察字段,并根据此字段的值绑定visible
。然后它不会从可观察数组中删除,但用户将无法看到它。
第三种方法
为index
创建一个额外的Rate
字段,并在父视图模型中(包含self.rates
的字段)保留lastIndex
,初始值设置为0.然后添加费率的功能如下所示:
self.newRate = function () {
var rate = new Rate({id: self.id});
rate.isEditing(true);
rate.isNew = true;
rate.index = lastIndex++;
rate = ko.validatedObservable(rate);
self.vendor().rates.push(rate);
};
删除项目的功能将使用谓词函数,如下所示:
self.editRateCancel = function (item) {
if (item.isNew === true) {
self.vendor().rates.remove(function (value) {
// remember about parenthesis after value()
// because it's an instance of validatedObservable()
// and not an instance of Rate()
return value().index == item.index;
});
} else {
item.cancelEdit();
ko.utils.arrayForEach(self.unitsOfMeasure(), function (uom) {
if(item.cacheUnitOfMeasureID === uom.value) {
item.selectedUOM(uom);
}
});
}
};
我继续使用第三种方法,但第二种方法也可以接受。