3

我有一个看起来像这样的 observableArray:

this.menuItems = ko.observableArray([
    { name: "level1", subItems: [
        { name: "level1-1" },
        { name: "level1-2" }
    ] },
    { name: "level2" },
    { name: "level3", subItems: [
        { name: "level3-1" },
        { name: "level3-2", subItems: [
            { name: "level3-2-1" }
        ] },
    ] },
    { name: "level4" }
]);

这会呈现一个多级导航菜单。所以有些项目可以有子项目,有些则没有。并且级别的数量是未知的。

现在我有一个“过滤导航”输入来过滤这些东西。

var self = this,
    menuFilter = ko.observable(""),
    filter = menuFilter().toLowerCase();

    if (filter === "") {
        return self.menuItems();
    } else {
        return ko.utils.arrayFilter(self.menuItems(), function (item) {
            if (item.name.toLowerCase().indexOf(filter) !== -1) {
                return true;
            }
        });
    }

这对顶级项目很有用,但我不确定循环遍历的最佳方式self.menuItems().subItems,然后是下一个级别,然后是下一个等。

有任何想法吗?

编辑:我刚刚创建了这个 JS Fiddle,它似乎正在工作。现在我必须弄清楚如何在我的 [稍微复杂的] 应用程序上运行它。

http://jsfiddle.net/KSrzL/7/

编辑(再次):我的最新问题是顶层没有信息,所以我必须从 START 开始.children,这不起作用。

http://jsfiddle.net/KSrzL/8/

4

1 回答 1

2

这似乎有效:http: //jsfiddle.net/MRtRm/

关键部分:

self.nonNullItems = function(arr) {
    return arr.filter(function(x) { return x !== null; });
};

self.filteredObjectOrNull = function(obj, query) {
    if (obj.hasOwnProperty('children')) {
        var filteredChildren = self.nonNullItems(obj.children.filter( function(x) { return self.filteredObjectOrNull(x, query); }));
        if (filteredChildren.length > 0)
            return {name: obj.name, children: filteredChildren};
    }

    if (self.matchText(obj.name, query))
            return obj;

    return null;
};

self.filterItems = function() {
    var filter = self.itemFilter();

    if (filter === "") {
        return self.items();
    } else {
        return self.nonNullItems(self.items().map( function(x) { return self.filteredObjectOrNull(x, filter); }));
    }
}

我认为它可以通过几种方式进行简化,但它似乎通过了我所做的测试。(您应该添加更多级别的菜单以确保。)

于 2013-05-30T21:40:20.953 回答