敲除 tbody 过滤器父/子
knockout tbody filter parent / childs
我有以下嵌套数据结构 (viewmodel):
projects ( projectid, project_name )
|--- subprojects ( parent_projectid, subproject_name )
我想将 "subprojects" 过滤为 "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 中计算某些东西来获取过滤的子项目,过滤器 "mechanism" 应该只在渲染 tbody 中工作(如果可能的话)
一旦您不再认为您的观点应该是聪明的,这就很容易了。您的视图应该反映您的模型 - 不要强迫它做更多的事情。
如果要显示这个结构:
- 父级 1
- 儿童 1.1
- 儿童 1.2
- 父 2
- 儿童 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>
我有以下嵌套数据结构 (viewmodel):
projects ( projectid, project_name )
|--- subprojects ( parent_projectid, subproject_name )
我想将 "subprojects" 过滤为 "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 中计算某些东西来获取过滤的子项目,过滤器 "mechanism" 应该只在渲染 tbody 中工作(如果可能的话)
一旦您不再认为您的观点应该是聪明的,这就很容易了。您的视图应该反映您的模型 - 不要强迫它做更多的事情。
如果要显示这个结构:
- 父级 1
- 儿童 1.1
- 儿童 1.2
- 父 2
- 儿童 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>