Javascript 如何在表的列中嵌入树结构

Javascript 如何在表的列中嵌入树结构,javascript,angular,Javascript,Angular,我想构建一个UI,在列表中显示项目,并在列表的其他列中显示其他详细信息。当一个项目包含子项目时,我可以展开该项目,并将其他行插入表中,项目的名称将缩进,但其余列将正常显示 挑战在于通常树结构是递归完成的。但不能让节点作为子行的父节点,否则它会破坏表 我能够得到一个概念证明,就像这样: <table> <thead> <th>Item Name</th> <th>Summary</th> <t

我想构建一个UI,在列表中显示项目,并在列表的其他列中显示其他详细信息。当一个项目包含子项目时,我可以展开该项目,并将其他行插入表中,项目的名称将缩进,但其余列将正常显示

挑战在于通常树结构是递归完成的。但不能让节点作为子行的父节点,否则它会破坏表

我能够得到一个概念证明,就像这样:

<table>
  <thead>
    <th>Item Name</th>
    <th>Summary</th>
    <th>Priority</th>
  </thead>
  <ng-template ngFor let-root [ngForOf]="['a','b','c']">
    <tr>
      <td style="padding-left: 0;">{{root}}</td>
      <td>Summary for {{root}}</td>
      <td>None</td>
    </tr>
    <ng-template ngFor let-child [ngForOf]="['1','2','3']">
      <tr>
        <td style="padding-left: 1em;">{{child}}</td>
        <td>Summary for {{child}}</td>
        <td>None</td>
      </tr>
    </ng-template>
  </ng-template>
</table>
<ng-template #node>
  <tr><!-- current node --></tr>
  <ng-container *ngIf="expanded">
    <ng-container ngFor let-child [ngForOf]="children">
      <ng-container *ngTemplateOutlet="node; context:child"></ng-container>
    </ng-container>
  </ng-container>
</ng-template>
<table>
  <thead><!-- column headers --></thead>
  <ng-container *ngTemplateOutlet="node; context: root"></ng-container>
</table>

项目名称
总结
优先
{{root}}
{{root}}的摘要
没有一个
{{child}}
{{child}摘要
没有一个
这是因为
不会作为DOM中的节点呈现

接下来,我尝试创建一个组件来表示这个概念:

<tr>
  <td style="padding-left: calc({{depth}}*1em);">
    {{item.nodeName()}}
  </td>
  <td *ngIf="details">{{item.summary}}</td>
  <td *ngIf="details">{{item.priority_name}}</td>
</tr>
<tr *ngIf="loading">
  <td *ngIf="details" style="padding-left: calc({{depth+1}}*1em);" colspan=3>Loading...</td>
  <td *ngIf="! details" style="padding-left: calc({{depth+1}}*1em);">Loading...</td>
</tr>
<ng-template ngFor let-child [ngForOf]="item.children">
  <item-node [item]="child" depth="depth+1" [details]="details"></item-node>    
</ng-template>

{{item.nodeName()}}
{{item.summary}
{{item.priority_name}
加载。。。
加载。。。
不幸的是,这不起作用,因为
在DOM中创建了一个打破表的节点


有没有一种不在DOM中插入无关节点的方法可以做到这一点?

解决方案是使用
创建递归模板,如下所示:

<table>
  <thead>
    <th>Item Name</th>
    <th>Summary</th>
    <th>Priority</th>
  </thead>
  <ng-template ngFor let-root [ngForOf]="['a','b','c']">
    <tr>
      <td style="padding-left: 0;">{{root}}</td>
      <td>Summary for {{root}}</td>
      <td>None</td>
    </tr>
    <ng-template ngFor let-child [ngForOf]="['1','2','3']">
      <tr>
        <td style="padding-left: 1em;">{{child}}</td>
        <td>Summary for {{child}}</td>
        <td>None</td>
      </tr>
    </ng-template>
  </ng-template>
</table>
<ng-template #node>
  <tr><!-- current node --></tr>
  <ng-container *ngIf="expanded">
    <ng-container ngFor let-child [ngForOf]="children">
      <ng-container *ngTemplateOutlet="node; context:child"></ng-container>
    </ng-container>
  </ng-container>
</ng-template>
<table>
  <thead><!-- column headers --></thead>
  <ng-container *ngTemplateOutlet="node; context: root"></ng-container>
</table>

还有更多细节需要解决,比如如何使缩进工作(需要跟踪深度,并添加基于深度缩进的样式),必须传递要从上下文中提取的变量,等等。但是根本问题是,如何避免DOM中有不必要的元素,使用
解决,子节点使用递归
代替独立组件进行处理


详细信息请阅读

解决方案是使用
创建递归模板,如下所示:

<table>
  <thead>
    <th>Item Name</th>
    <th>Summary</th>
    <th>Priority</th>
  </thead>
  <ng-template ngFor let-root [ngForOf]="['a','b','c']">
    <tr>
      <td style="padding-left: 0;">{{root}}</td>
      <td>Summary for {{root}}</td>
      <td>None</td>
    </tr>
    <ng-template ngFor let-child [ngForOf]="['1','2','3']">
      <tr>
        <td style="padding-left: 1em;">{{child}}</td>
        <td>Summary for {{child}}</td>
        <td>None</td>
      </tr>
    </ng-template>
  </ng-template>
</table>
<ng-template #node>
  <tr><!-- current node --></tr>
  <ng-container *ngIf="expanded">
    <ng-container ngFor let-child [ngForOf]="children">
      <ng-container *ngTemplateOutlet="node; context:child"></ng-container>
    </ng-container>
  </ng-container>
</ng-template>
<table>
  <thead><!-- column headers --></thead>
  <ng-container *ngTemplateOutlet="node; context: root"></ng-container>
</table>

还有更多细节需要解决,比如如何使缩进工作(需要跟踪深度,并添加基于深度缩进的样式),必须传递要从上下文中提取的变量,等等。但是根本问题是,如何避免DOM中有不必要的元素,使用
解决,子节点使用递归
代替独立组件进行处理

有关详细信息,请阅读