挖空和选择器的数组过滤问题

An array filtering issue with knockout and selectors

本文关键字:数组 过滤 问题 选择器      更新时间:2023-09-26

我有一个文本数组,我显示在<select>中。

文本可能有不同的版本号,我想仅根据最新版本过滤<select>

我想有更优雅的方法可以做到这一点(欢迎建议(,但我选择使用 2 <select> s 设置为根据复选框的替代可见性。

代码是一个黑客,但结果看起来相当不错。不幸的是,有一个错误。

我有两个可观察量指示它们各自数组中的选定选项:

self.SelectedText = ko.observable();
self.SelectedUnique = ko.observable();

两者都有订阅,但我无法在两个订阅中将它们链接在一起,所以我选择了一个独立在另一个上独立,如下所示:

self.SelectedUnique.subscribe(function (text) {
    if (text) {
        self.SelectedText(text);
    }
});

但是,不同步。

场景 1:选择文本 1、2、3。[确定]场景 2:选择文本 2;选中"仅限最新版本"

这会导致不显示任何选项("选择..."(。不是我想要的。

情况变得更糟。

场景 3:取消选中; 选择文本 3;然后再次选中"仅最新版本"。

现在,选择的选项设置为选择未过滤的选项2。

可能有一个简单的问题。我只是无法让它工作。这是小提琴: 小提琴: http://jsfiddle.net/h5mt51gv/6/

感谢所有的帮助和建议!

我已经简化了你的方法:

  • <select>绑定到计算的选项列表 ( visibleTextBatches (
  • 此计算列表取决于复选框的状态 ( latestOnly (,有效地在完整列表和过滤列表之间切换
  • 过滤列表(latestTextBatches(是另一个计算,它保存每个组的最新版本
  • <select>将实际选定的TextBatch对象存储在可观察量(selectedTextBatch (
  • 有一个对visibleTextBatches的订阅,当筛选列表时,该订阅会导致最新的可选TextBatch成为当前。当列表未筛选时,它不执行任何操作。

function TextBatch(data) {
    this.textbatchId = data.textbatchId;
    this.parentId = data.parentId;
    this.version = data.version;
    this.title = ko.observable(data.title);
}
function ViewModel() {
    var self = this;
    // read up on the mapping plugin, too
    self.textBatches = ko.observableArray([
        new TextBatch({textbatchId: 1, parentId: 1, version: 1, title: "TB1.1"}),
        new TextBatch({textbatchId: 2, parentId: 1, version: 2, title: "TB1.2"}),
        new TextBatch({textbatchId: 3, parentId: 3, version: 1, title: "TB2.1"})
    ]);
    self.selectedTextBatch = ko.observable();
    self.latestOnly = ko.observable(false);
    self.latestTextBatchGroups = ko.computed(function () {
        var latest = {};
        ko.utils.arrayForEach(self.textBatches(), function (batch) {
            if (!latest.hasOwnProperty(batch.parentId) || 
                batch.version > latest[batch.parentId].version
            ) latest[batch.parentId] = batch;
        });
        return latest;
    });
    self.latestTextBatches = ko.computed(function () {
        return ko.utils.arrayFilter(self.textBatches(), function (batch) {
            return batch === self.latestTextBatchGroups()[batch.parentId];
        });
    });
    self.visibleTextBatches = ko.computed(function () {
        return self.latestOnly() ? self.latestTextBatches() : self.textBatches();
    });
    self.visibleTextBatches.subscribe(function () {
        var selectedBatch = self.selectedTextBatch();
        if (selectedBatch && self.latestOnly()) {
            self.selectedTextBatch(
                self.latestTextBatchGroups()[selectedBatch.parentId]
            );
        }
    });
}
ko.applyBindings(new ViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div>
    <select data-bind="
        options: visibleTextBatches, 
        optionsText: 'title',
        optionsCaption: 'Select...',
        value: selectedTextBatch
    " />
</div>
<div>
    <input type="checkbox" id="chkLatestOnly" data-bind="checked: latestOnly" />
    <label for="chkLatestOnly">Latest only</label>
</div>
<hr />
<pre data-bind="text: ko.toJSON($root, null,2)"></pre>