我有一个递归数据结构(通过children
属性递归),如下所示:
export interface IExecutableLog {
round: number;
log: string;
}
export interface IExecutableResult {
uid: string;
name: string;
desc: string;
status: string;
passedRounds: number;
totalRound: number;
children?: IExecutableResult[];
statementType?: string;
logs?: IExecutableLog[];
}
export interface ISummary {
title: string;
jobName: string;
timestamp: Date;
tester: string;
result: string;
executionId: string;
testJobId: string;
resultDetails: IExecutableResult;
}
我想从后端显示Isummary类型的数据。
我尝试定义如下组件:
// pats-report-element.component.ts
import { Component, Input, ViewEncapsulation } from '@angular/core';
import { IExecutableResult } from '../pats-report.interface';
@Component({
selector: 'pats-report-element',
templateUrl: 'app/report/basic/pats-report-element.html',
encapsulation: ViewEncapsulation.None,
})
export class PatsReportElementComponent {
@Input()
public data: IExecutableResult;
}
// app/report/basic/pats-report-element.html
<tr>
<td>{{data?.name}}</td>
<td>{{data?.status}}</td>
<td>{{data?.rounds}}</td>
<td>{{data?.passedRounds}}</td>
<td>{{data?.rounds > 0 ? (data.passedRounds / data.rounds) * 100 + "%" : "NA"}}</td>
<td>{{data?.timestamp | date:"y-MM-dd HH:mm:ss"}}</td>
</tr>
<template [ngIf]="data && data.children">
<template ngFor let-item [ngForOf]="data.children" let-i="index">
<pats-report-element [data]="item"></pats-report-element>
</template>
</template>
但渲染的DOM将包含在<table></table>
标记内无效的主机元素'pats-report-element'。 DOM如下:
我检查了angular2 doc,似乎attribute-directives是正确的选择。但我找不到像使用PatsReportElementComponent那样使用带有属性指令的模板的方法。
那么实现目标的正确方法是什么?
[更新1]
尝试了@GünterZöchbauer的建议,仍未解决我的问题。渲染的DOM仍然没有达到预期的效果(<tr></tr>
仍然没有被展平)。
答案 0 :(得分:1)
您可以使用属性选择器
@Component({
selector: '[pats-report-element]',
然后你可以添加像
这样的元素<tr pats-report-element [data]="item"></tr>
如果没有它的选择器元素,就无法渲染元素。
答案 1 :(得分:1)
经过多次努力,我仍未能完成原生angular2。我最终得到了第三方图书馆 - ag-grid-ng2。它运作良好,除了它对我的要求有点过分。
答案 2 :(得分:0)
我不确定它是否能解决您的问题,在模板中递归引用相同组件的组件中,您应该在指令中自引用它。
// pats-report-element.component.ts 从&#39; @ angular / core&#39;中导入{Component,Input,ViewEncapsulation}; 从&#39; ../ pats-report.interface&#39;;
导入{IExecutableResult}@Component({
selector: 'pats-report-element',
directives: [forwardRef(() => PatsReportElementComponent )], // <<<<<< change
templateUrl: 'app/report/basic/pats-report-element.html',
encapsulation: ViewEncapsulation.None,
})
export class PatsReportElementComponent {
@Input()
public data: IExecutableResult;
}
// app/report/basic/pats-report-element.html
<tr>
<td>{{data?.name}}</td>
<td>{{data?.status}}</td>
<td>{{data?.rounds}}</td>
<td>{{data?.passedRounds}}</td>
<td>{{data?.rounds > 0 ? (data.passedRounds / data.rounds) * 100 + "%" : "NA"}}</td>
<td>{{data?.timestamp | date:"y-MM-dd HH:mm:ss"}}</td>
</tr>
<template [ngIf]="data && data.children">
<template ngFor let-item [ngForOf]="data.children" let-i="index">
<pats-report-element [data]="item"></pats-report-element>
</template>
</template>
看看这是否适合你。
答案 3 :(得分:0)
您可以在<table>
内放置另一个<my-component-selector>
作为关卡子级。只需在当前级别的表格标签关闭后执行此操作即可:
<table>
<tbody>
<tr>
<td>{{level.id}}</td>
<td>{{level.title}}</td>
</tr>
</tbody>
</table>
<div *ngFor="let item of level.childLevels">
<my-component-selector [level]="item">
<!-- Here will be inserted another instance of this HTML file with itself table and itself recursion -->
</my-component-selector>
</div>
在每个层次结构中都有这样的组件:
@Component({
selector: 'my-component-selector',
templateUrl: './my-recursive.component.html'
})
export class MyRecursiveComponent implements OnInit {
@Input() level: LevelItem;
onInit() {
if (!level) {
loadRootLevelByNetwork();
}
}
}
level
变量是通过HTML中的[level]="item"
从外部组件设置的,或者是由网络加载的(对于根组件)。