淘汰tbody过滤器父母/孩子

时间:2015-12-27 10:24:04

标签: knockout.js foreach filter nested

我有以下嵌套数据结构(viewmodel):

projects ( projectid, project_name )
  |--- subprojects ( parent_projectid, subproject_name )

我想将“子项目”过滤为“parent_projectid”,这是来自父项目(“projectid”)的id。 “tbody”应自动呈现子项目,例如:

     <tbody >
            <!-- ko foreach: projects -->
            <tr>
                <td data-bind="text: projectid"></td>
                <td data-bind="text: project_name "></td>
                <td class="add" href="#" data-bind="click: addsubproject">Add Subproject</td>
            </tr>

    *** here should the filter applied : ***    
             <!-- ko foreach: subprojects // show only subprojects with "parent_projectid = projectid" -->
                    <tr>
                        <td></td>
                        <td data-bind="text: parent_projectid"></td>
                        <td data-bind="text: subproject_name "></td>
                    </tr>
                    <!-- /ko -->    
            <!-- /ko -->
        </tbody>

我该如何申请?我不想在viewmodel中计算某些内容来获取已过滤的子项目,过滤器“机制”应仅在呈现tbody中工作(如果可能)

1 个答案:

答案 0 :(得分:2)

一旦你不再认为你的观点应该是聪明的,这很容易。您的观点应该反映您的模型 - 不要强迫它做更多的事情。

如果要显示此结构:

  • 家长1
    • 儿童1.1
    • 儿童1.2
  • 家长2
    • Child 2.1
    • 儿童2.2
那么这就是你的模型应该是什么样子的样子。相应地构建它:

// we only really have one type of object in your scenario, let's call it "Project"
function Project(data) {
    this.id = data.id;
    this.name = ko.observable(data.name);
    this.children = ko.observableArray(ko.utils.arrayMap(data.children, function (child) {
        // NB this is recursive
        return new Project(child);
    }));
}

// this will be the main viewmodel
function ProjectTree() {
    var root = new Project({id: 0, name: "root", children: data});
    this.projects = root.children;
}

假设您从服务器检索的data是一个平面的项目对象数组,让我们将它们预处理到树中。再次 - 这是关键部分 - 如果你想显示树形数据,你应该有树形数据。

$.get("projects.json").then(function (data) {
    var index = {}, children = {};
    // index objects by id and by parentid
    data.forEach(function (project) {
        index[project.id] = project;
        if (project.parentid in index) {
            children[project.parentid].push(project);
        } else {
            children[project.parentid] = [project];
        }
    });
    // link up everything into a tree
    Object.keys(index).forEach(function (project) {
        project.children = children[project.id] || [];
    });
    return children[0]; // or whatever the parent ID of top level projects is
}).done(function (data) {
    var vm = new ProjectTree(data);
    ko.applyBindings(vm);
});

现在视图可以是它应该是什么 - 直截了当:

 <tbody data-bind="foreach: projects">
    <tr>
        <td data-bind="text: id"></td>
        <td data-bind="text: name"></td>
        <td class="add" href="#" data-bind="click: addsubproject">Add Subproject</td>
    </tr>
    <!-- ko foreach: children -->
    <tr>
        <td></td>
        <td data-bind="text: $parent.id"></td>
        <td data-bind="text: name"></td>
    </tr>
    <!-- /ko -->    
</tbody>