如何创建嵌套的递归表,可以在Angular中向下钻取x级别 [英] how can I create a nested, recursive table that can drill down x levels in Angular

查看:79
本文介绍了如何创建嵌套的递归表,可以在Angular中向下钻取x级别的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要用嵌套子任务的数据制作表.我需要使该表递归.关于ngFor递归地显示数据的文献很多,但不是以表格格式显示.有很多事情使表格难以使用(例如,在td标签之外使用div标签等)

I need to make a table with data with nested subtasks. I need to make this table recursive. There is a lot of literature about ngFor recursively showing data, but not in a table format. There are a lot of things that make tables harder to work with(e.g. using div tags outside of td tags, etc.)

这是我到目前为止所获得的成就.

here is a stackblitz of what I got so far.

https://stackblitz.com /edit/angular-xk9nw6?file=src%2Fapp%2Ftable%2Ftable.component.html

如您所见,在遇到ngFor问题之前,我只能向下钻取一个级别

As you can see, I can only drill down a single level before I encounter issues with 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 },
                    ]
                }]
            }
        ]
    }
];

我希望获得一个可递归处理数据的表,将子任务置于其父任务下,并将子子任务置于其父子任务下,等等.

I am hoping to achieve a table that handles data recursively, placing subtasks under their parent tasks, and sub-sub-tasks under their parent subtasks, etc, etc.

当前,我只能使用非动态标记向下钻取一个级别. 关于无序列表如何工作的例子很多,但是这些方法似乎也不适用于表.将选择器标签放在其自己的标记内会导致问题.

currently, I can only drill down one level in with non dynamic markup. there are plenty of examples of how this works with unordered lists, but these methods don't seem to work with tables as well. dropping a selector tag on inside it's own markup causes issues.

推荐答案

一个递归组件,它仅使像这样的组件

A recursive component it's only make a component like

@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标签的方法,并且还要注意一下,我们必须使用带有子对象的对象来提供组件.如果我们有一个数组,例如

I like know the "level of recursion" it's the reason of this "index". WE must use to avoid create extra html tags, and take a look too, that we must feed the component with an object with children, so. if we has an array, like

items = [{ title: "item1" },
    {
      title: "item2", children: [
        { title: "item 2.1" },
        { title: "item 2.2" }]
    },
    { title: "item3" }
    ]

我们可以创建带有孩子的即时"对象,而我们的.html将是

We can create "on fly" an object with children and our .html will be

<recursive-component [item]="{children:menu}"  ></recursive-component>

但是您不能使用表,因为总是会在另一个表中获得一个表,或者在另一个tr中获得一个tr

But you can not do using tables, because always you'll get a table inside another table or a tr inside another tr

如果需要使用表,则可以采取另一种方法:根据数据生成一个数组,是否进行扩展.因此,您可以执行类似

If you need use table you can take another aproach: generate an array based in your data and if is expanded or not. So, you can do a function like

  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 中,您可以看到两个选项

In stackblitz, you can see the two options

注意:我简单地使用div(单击)或tr(单击)来更改展开"属性.

NOTE: I simple use div (click) or tr (click) to change the "expanded" property.

注意2:在堆叠闪电战中,我使用索引"来更改元素的边距或填充

NOTE2: In the stackblitz I use the "index" to change the margin or the padding of the elements

这篇关于如何创建嵌套的递归表,可以在Angular中向下钻取x级别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆