我需要制作带有嵌套子任务的数据的表。我需要使这个表递归。关于NGFOR的文献有很多文献递归显示数据,但没有以表格格式显示。有很多事情使桌子更难使用(例如,使用TD标签之外的DIV标签等)
)这是我到目前为止得到的堆叠。
https://stackblitz.com/edit/angular-xk9nw6?file=src/app/table/table;
您可以看到,我只能在遇到NGFOR
的问题之前向下钻一个级别<H1 style="text-indent: 10px">Table</H1>
<style>
table{
background:rgb(223, 221, 221);
}
</style>
<table class="table">
<thead>
<tr>
<th>expand</th>
<th>task id</th>
<th>task name</th>
<th>button</th>
</tr>
</thead>
<tbody *ngFor="let datum of data; index as i">
<tr>
<td class="" (click)="task(datum, i); $event.stopPropagation()" >
<i [ngClass]="(index != i)?'fas fa-plus':'fas fa-minus'"></i>
</td>
<td class="">{{datum.taskID}}</td>
<td class="">{{datum.taskName}}</td>
<td ALIGN="center">
<!-- <i class="fas fa-ellipsis-h" data-toggle="dropdown"></i> -->
<select>
<option (click)="dropdown(datum)" value="add">Add</option>
<option (click)="dropdown(datum)" value="edit">Edit</option>
<option (click)="dropdown(datum)" value="delete">Delete</option>
</select>
</td>
</tr>
<tr [hidden]="index != i" *ngFor="let subtask of datum.subtasks; index as j" >
<div [hidden]="!subtask.subtasks">
<td class="" style="text-indent: 15px" (click)="subtaskQ(subtask, j)"> <i class="fas fa-plus"></i> </td>
</div>
<div [hidden]="subtask.subtasks">
<td class="" style="text-indent: 15px" (click)="subtaskQ(subtask, j)"></td>
</div>
<td class="">{{subtask?.taskID}}</td>
<td class="">{{subtask?.taskName}}</td>
<td ALIGN="center">
<select>
<option (click)="dropdown(subtask)" value="add">Add</option>
<option (click)="dropdown(subtask)" value="edit">Edit</option>
<option (click)="dropdown(subtask)" value="delete">Delete</option>
</select>
</td>
</tr>
<tr [hidden]="index != i && index !=j" *ngFor="let subtaskL of subtask; index as e" >
<td class="" style="text-indent: 15px" (click)="subtaskQ(subtask, j)"></td>
<td class="">{{subtaskL?.taskID}}</td>
<td class="">{{subtaskL?.taskName}}</td>
<td ALIGN="center">
<select>
<option (click)="dropdown(subtask)" value="add">Add</option>
<option (click)="dropdown(subtask)" value="edit">Edit</option>
<option (click)="dropdown(subtask)" value="delete">Delete</option>
</select>
</td>
</tr>
</tbody>
</table>
组件
import { Component, OnInit,ViewChild } from '@angular/core';
import { sampleData } from '../datasource';
@Component({
selector: 'app-table',
templateUrl: './table.component.html',
styleUrls: ['./table.component.css']
})
export class TableComponent implements OnInit {
constructor() { }
@ViewChild('treegrid')
public data: Object[];
public foo: boolean;
public subtaskArray: any;
public subSubtaskArray: any;
public index: number;
dropdown(e){
console.log(e);
}
task(e, i){
console.log(e);
this.subtaskArray = e.subtasks
this.index = i;
}
subtaskQ(e, j){
this.subSubtaskArray = e.subtasks;
console.log(j);
console.log(e);
}
switch(){
if(this.foo){
this.foo =false;
} else {
this.foo = true;
}
}
ngOnInit(): void {
this.data = sampleData;
}
}
样本数据
/**
* Test cases data source
*/
export let sampleData: Object[] = [
{
taskID: 1,
taskName: 'Planning',
startDate: new Date('02/03/2017'),
endDate: new Date('02/07/2017'),
progress: 100,
duration: 5,
priority: 'Normal',
approved: false,
isInExpandState: true,
subtasks: [
{ taskID: 2, taskName: 'Plan timeline', startDate: new Date('02/03/2017'), endDate: new Date('02/07/2017'), duration: 5, progress: 100, priority: 'Normal', approved: false },
{ taskID: 3, taskName: 'Plan budget', startDate: new Date('02/03/2017'), endDate: new Date('02/07/2017'), duration: 5, progress: 100, approved: true },
{ taskID: 4, taskName: 'Allocate resources', startDate: new Date('02/03/2017'), endDate: new Date('02/07/2017'), duration: 5, progress: 100, priority: 'Critical', approved: false },
{ taskID: 5, taskName: 'Planning complete', startDate: new Date('02/07/2017'), endDate: new Date('02/07/2017'), duration: 0, progress: 0, priority: 'Low', approved: true }
]
},
{
taskID: 6,
taskName: 'Design',
startDate: new Date('02/10/2017'),
endDate: new Date('02/14/2017'),
duration: 3,
progress: 86,
priority: 'High',
isInExpandState: false,
approved: false,
subtasks: [
{ taskID: 7, taskName: 'Software Specification', startDate: new Date('02/10/2017'), endDate: new Date('02/12/2017'), duration: 3, progress: 60, priority: 'Normal', approved: false },
{ taskID: 8, taskName: 'Develop prototype', startDate: new Date('02/10/2017'), endDate: new Date('02/12/2017'), duration: 3, progress: 100, priority: 'Critical', approved: false },
{ taskID: 9, taskName: 'Get approval from customer', startDate: new Date('02/13/2017'), endDate: new Date('02/14/2017'), duration: 2, progress: 100, approved: true },
{ taskID: 10, taskName: 'Design Documentation', startDate: new Date('02/13/2017'), endDate: new Date('02/14/2017'), duration: 2, progress: 100, approved: true },
{ taskID: 11, taskName: 'Design complete', startDate: new Date('02/14/2017'), endDate: new Date('02/14/2017'), duration: 0, progress: 0, priority: 'Normal', approved: true }
]
},
{
taskID: 12,
taskName: 'Implementation Phase',
startDate: new Date('02/17/2017'),
endDate: new Date('02/27/2017'),
priority: 'Normal',
approved: false,
duration: 11,
subtasks: [
{
taskID: 13,
taskName: 'Phase 1',
startDate: new Date('02/17/2017'),
endDate: new Date('02/27/2017'),
priority: 'High',
approved: false,
duration: 11,
subtasks: [{
taskID: 14,
taskName: 'Implementation Module 1',
startDate: new Date('02/17/2017'),
endDate: new Date('02/27/2017'),
priority: 'Normal',
duration: 11,
approved: false,
subtasks: [
{ taskID: 15, taskName: 'Development Task 1', startDate: new Date('02/17/2017'), endDate: new Date('02/19/2017'), duration: 3, progress: '50', priority: 'High', approved: false },
{ taskID: 16, taskName: 'Development Task 2', startDate: new Date('02/17/2017'), endDate: new Date('02/19/2017'), duration: 3, progress: '50', priority: 'Low', approved: true },
{ taskID: 17, taskName: 'Testing', startDate: new Date('02/20/2017'), endDate: new Date('02/21/2017'), duration: 2, progress: '0', priority: 'Normal', approved: true },
{ taskID: 18, taskName: 'Bug fix', startDate: new Date('02/24/2017'), endDate: new Date('02/25/2017'), duration: 2, progress: '0', priority: 'Critical', approved: false },
{ taskID: 19, taskName: 'Customer review meeting', startDate: new Date('02/26/2017'), endDate: new Date('02/27/2017'), duration: 2, progress: '0', priority: 'High', approved: false },
{ taskID: 20, taskName: 'Phase 1 complete', startDate: new Date('02/27/2017'), endDate: new Date('02/27/2017'), duration: 0, priority: 'Low', approved: true }
]
}]
},
{
taskID: 21,
taskName: 'Phase 2',
startDate: new Date('02/17/2017'),
endDate: new Date('02/28/2017'),
priority: 'High',
approved: false,
duration: 12,
subtasks: [{
taskID: 22,
taskName: 'Implementation Module 2',
startDate: new Date('02/17/2017'),
endDate: new Date('02/28/2017'),
priority: 'Critical',
approved: false,
duration: 12,
subtasks: [
{ taskID: 23, taskName: 'Development Task 1', startDate: new Date('02/17/2017'), endDate: new Date('02/20/2017'), duration: 4, progress: '50', priority: 'Normal', approved: true },
{ taskID: 24, taskName: 'Development Task 2', startDate: new Date('02/17/2017'), endDate: new Date('02/20/2017'), duration: 4, progress: '50', priority: 'Critical', approved: true },
{ taskID: 25, taskName: 'Testing', startDate: new Date('02/21/2017'), endDate: new Date('02/24/2017'), duration: 2, progress: '0', priority: 'High', approved: false },
{ taskID: 26, taskName: 'Bug fix', startDate: new Date('02/25/2017'), endDate: new Date('02/26/2017'), duration: 2, progress: '0', priority: 'Low', approved: false },
{ taskID: 27, taskName: 'Customer review meeting', startDate: new Date('02/27/2017'), endDate: new Date('02/28/2017'), duration: 2, progress: '0', priority: 'Critical', approved: true },
{ taskID: 28, taskName: 'Phase 2 complete', startDate: new Date('02/28/2017'), endDate: new Date('02/28/2017'), duration: 0, priority: 'Normal', approved: false }
]
}]
},
{
taskID: 29,
taskName: 'Phase 3',
startDate: new Date('02/17/2017'),
endDate: new Date('02/27/2017'),
priority: 'Normal',
approved: false,
duration: 11,
subtasks: [{
taskID: 30,
taskName: 'Implementation Module 3',
startDate: new Date('02/17/2017'),
endDate: new Date('02/27/2017'),
priority: 'High',
approved: false,
duration: 11,
subtasks: [
{ taskID: 31, taskName: 'Development Task 1', startDate: new Date('02/17/2017'), endDate: new Date('02/19/2017'), duration: 3, progress: '50', priority: 'Low', approved: true },
{ taskID: 32, taskName: 'Development Task 2', startDate: new Date('02/17/2017'), endDate: new Date('02/19/2017'), duration: 3, progress: '50', priority: 'Normal', approved: false },
{ taskID: 33, taskName: 'Testing', startDate: new Date('02/20/2017'), endDate: new Date('02/21/2017'), duration: 2, progress: '0', priority: 'Critical', approved: true },
{ taskID: 34, taskName: 'Bug fix', startDate: new Date('02/24/2017'), endDate: new Date('02/25/2017'), duration: 2, progress: '0', priority: 'High', approved: false },
{ taskID: 35, taskName: 'Customer review meeting', startDate: new Date('02/26/2017'), endDate: new Date('02/27/2017'), duration: 2, progress: '0', priority: 'Normal', approved: true },
{ taskID: 36, taskName: 'Phase 3 complete', startDate: new Date('02/27/2017'), endDate: new Date('02/27/2017'), duration: 0, priority: 'Critical', approved: false },
]
}]
}
]
}
];
我希望获得一张递归处理数据的表,将子任务放在其父任务下,并在其父子任务下等子任务等等。
当前,我只能通过非动态标记钻一个级别。有很多例子说明这与无序列表一起使用,但是这些方法似乎也不适合表。在内部放置选择器标签会导致问题。
递归组件它仅制成一个
之类的组件@Component({
selector: 'recursive-component',
template:`
<ng-container>
{{index}}--some template--, e.g {{item.title}}
</ng-container>
<ng-container *ngIf="item.children">
<recursive-component *ngFor="let item of item.children" [index]="index+1" [item]="item">
</recursive-component>
<ng-container> `
})
export class MenuComponent {
@Input() item:any
@Input() index:number=0;
}
我喜欢知道"递归水平",这是该"索引"的原因。我们必须用来避免创建额外的HTML标签,并查看一下,以便我们必须用带孩子的对象为组件喂食。如果我们有一个数组,例如
items = [{ title: "item1" },
{
title: "item2", children: [
{ title: "item 2.1" },
{ title: "item 2.2" }]
},
{ title: "item3" }
]
我们可以创建带有孩子的对象"飞",我们的.html将为
<recursive-component [item]="{children:menu}" ></recursive-component>
,但是您无法使用表,因为始终您将在另一个表格或另一个tr
内获取tr如果您需要使用表,则可以采取另一个侵犯:在数据中生成一个基于数据的数组,以及是否扩展。因此,您可以执行
之类的函数 getItems(data, items,index) {
data.forEach(x => {
if (!items)
items=[];
items.push(x);
items[items.length-1].index=index
if (x.subtasks && x.expanded)
this.getItems(x.subtasks,items,index+1);
}
)
return items;
}
然后您可以简单
//In your .html
<table>
<tr (click)="expanded(item)" *ngFor="let item of items">
<td>{{item.taskID}}</td>
<td>{{item.taskName}}</td>
</tr>
</table>
//And in your .ts
ngOnInit()
{
this.items=this.getItems(this.sampleData,null,0)
}
expanded(item:any)
{
item.expanded=!item.expanded;
this.items=this.getItems(this.sampleData,null,0)
}
在Stackblitz中,您可以看到两个选项
注意:我简单使用Div(单击)或TR(单击)更改"扩展"属性。
Note2:在Stackblitz中,我使用"索引"来更改元素的边距或填充