我正在树表上创建一个摘要行,该树表也具有过滤功能(我正在使用ng Prime组件库,但我不认为这与错误或问题有密切关系)。我希望摘要行只摘要当前视图中的信息,因此当树展开或应用过滤器时,摘要应该更改。
我通过将一个函数设置为元素属性[attr.summaryFunction]=“summaryFunction],将行数据添加到Map中,从而实现了这个目标(i,rowData[col.field])",并使用ngDoCheck重新初始化Map。如果没有此步骤,则在ngDoCheck中重新初始化Map时,每次重画或更改都会累积总数,并导致错误的值。(我尝试用其他几个生命周期钩子ngOnInit、ngOnViewInit和ngOnChanges重新初始化Map,但唯一有效地重新初始化Map的生命周期钩子是ngDoCheck)。
我的方法非常好用(哎呀!),但是我在浏览器中得到ExpressionChangedAfterItHasBeenCheckedError,每列三次。为了解决这个错误,我尝试了文档中推荐的所有4种方法来修复错误:
1.使用不同的生命周期挂钩--〉总计不正确
1.我将这个.cd.detectChanges()添加到了汇总函数--〉无限循环中
1.我将if语句封装在setTimeout(()=〉if(statement){})--〉无限循环中
- Promise.resolve().then(()=〉if(语句){})--〉无限循环
同样,我的方法目前完全按照我的想法工作,我只是想让这些恼人的错误消失。我还想了解为什么通常的修复会导致无限循环。
这是我的TS层
export class PrimetreeComponent implements OnInit, DoCheck {
sampleData: TreeNode[] = []
columns: any[] = [];
summaryMap = new Map();
columnIndex = 0;
constructor(private nodeService: NodeService, private cd: ChangeDetectorRef) {}
ngOnInit(): void {
this.nodeService.getFilesystem().subscribe(data => {this.sampleData = data});
this.columns = [
{field: 'name', header: 'name'},
{field: 'size', header: 'size'},
{field: 'type', header: 'type'}]
}
ngDoCheck(): void {
this.summaryMap = new Map();
}
summaryFunction(columnIndex:number, rowData:any){
if(this.summaryMap.has(columnIndex)){
//if row data is a non-number string we just count the rows
if(Number(rowData)){
this.summaryMap.set(columnIndex, this.summaryMap.get(columnIndex)+Number(rowData));
} else {
this.summaryMap.set(columnIndex, this.summaryMap.get(columnIndex)+1)
}
} else {
if(Number(rowData)){
this.summaryMap.set(columnIndex, Number(rowData));
} else {
this.summaryMap.set(columnIndex, 1)
}
}
}
}
这是我的HTML模板:
<p-treeTable #tt [value]="sampleData" [columns]="columns">
<ng-template pTemplate="caption">
<div style="text-align: right">
<span class="p-input-icon-left">
<i class="pi pi-search"></i>
<input
pInputText
type="text"
size="50"
placeholder="Global Filter"
(input)="tt.filterGlobal($any($event.target).value, 'contains')"
style="width:auto"
/>
</span>
</div>
</ng-template>
<ng-template pTemplate="header" let-columns>
<tr>
<th *ngFor="let col of columns">
{{ col.header }}
</th>
</tr>
<tr>
<th *ngFor="let col of columns">
<input
pInputText
type="text"
class="w-full"
(input)="
tt.filter($any($event.target).value, col.field, col.filterMatchMode)
"
/>
</th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-rowNode let-rowData="rowData" >
<tr>
<td *ngFor="let col of columns; let i = index;" [attr.summaryFunction]="summaryFunction(i,rowData[col.field])">
<p-treeTableToggler
[rowNode]="rowNode"
*ngIf="i == 0"
(columnIndex)="i"
></p-treeTableToggler>
{{ rowData[col.field] }}
</td>
</tr>
</ng-template>
<ng-template pTemplate="emptymessage">
<tr>
<td [attr.colspan]="columns.length">No data found.</td>
</tr>
</ng-template>
<ng-template pTemplate="summary">
<tr>
<td *ngFor="let col of columns; let i = index;">
{{ col.header }}--sumMap--{{summaryMap.get(i) }}
</td>
</tr>
</ng-template>
1条答案
按热度按时间iszxjhcz1#
我不熟悉将函数绑定到elements属性的方法,但对我来说这似乎有点笨拙。如果我错了请纠正我,但这样做的原因是当节点添加到dom时有一种方法来触发函数?
我自己没有测试过这个,但是我认为你可以使用
@ContentChildren
装饰器see docs,它公开了一个观察对象,你可以订阅它来对内容dom的变化做出React,理想情况下,你可以在一个步骤中运行摘要创建和更新summaryMap。更新:
我对这个想法做了一些尝试,一个解决方案是使用
@ViewChildren
装饰器来获取当前呈现的所有行的QueryList,这可以通过以下方式实现:注意
<tr [ttRow]="rowNode" #tableRow [attr.file-size]="rowData.size">
上的模板ref以及将rowData.size绑定到元素的属性。然后,您可以获取当前挂载到dom的行列表rows,如下所示:
您可以找到此here的运行示例。