0

我的视图模型的属性上有一个 observableArray:

self.rates = ko.observableArray([])

数组的内容显示在 HTML 表格中。有一个按钮可以将项目添加到数组中。这些是经过验证的 observables:

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),但从底层数组返回的值是 of,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;
    },

如何从可观察数组中删除特定的已验证可观察对象?是否有任何实用功能可用?

4

2 回答 2

2

我刚遇到这个问题,我的研究把我带到了这里,所以我会记下我为解决它所做的工作。

淘汰赛中的 foreach 绑定允许使用 $index() 访问当前元素的索引。我没有使用将对象传递给删除函数的正常机制,而是传递了索引。

例子

通常:

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/

于 2016-01-19T19:51:16.403 回答
0

我遇到了同样的问题,这些是我尝试过的方法:

第一种方法

创建一个 observable 数组,并带有实例Rate和一个计算的 observable,它将从 Rate 中返回每个项目作为validatedObservable. 这种方法的问题在于,每次向数组添加或删除项目时,都会validatedObservable重新创建所有项目,这效率不高,并且会导致奇怪的 UI 行为。

第二种方法

为该字段的值创建一个额外的deleted可观察字段Rate并进行visible绑定。然后它不会从可观察数组中删除,但对用户不可见。

第三种方法

为父视图模型(包含 的)创建一个附加index字段,并将初始值设置为 0。然后添加速率的函数如下所示:Rateself.rateslastIndex

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

我继续采用第三种方法,但第二种方法您也可以接受。

于 2013-11-27T13:34:16.587 回答