Angular 异步管道传递的输入数据在子组件中为空,但在父组件中不为空
Angular input data passed by async pipe is null in child component although is not null in parent
我有一个奇怪的案例,我无法通过也不知道它是怎么发生的,所以我得到了名为 SiteComponent
的父组件
这里打字稿逻辑:
ngOnInit(): void {
this.subs.push(
this.route.data.subscribe(data => {
this.siteTemplate$ = this.dataService.getMappedData(`data${data.type}`).pipe(
map(_data => ({..._data, dataType: data.type })),
)
})
);
}
这里是模板文件代码:
<div class="app-site">
<ng-container *ngIf="!siteTemplate$ | async">
<div fxLayout="row"
fxLayoutAlign="center"
style="margin-top: 60px;">
<mat-spinner></mat-spinner>
</div>
</ng-container>
<ng-container *ngIf="siteTemplate$ | async">
<app-filters (filtersChanged)="applyFilters()"></app-filters>
<div class="app-site-section">
<div class="app-site-section-column" id="charts">
<app-linear-chart *ngFor="let record of (siteTemplate$ | async)?.chartsData.records"
[categories]="(siteTemplate$ | async)?.chartsData.categories"
[chartData]="record"
></app-linear-chart>
</div>
<div class="app-site-section-column">
<app-pie-chart *ngFor="let record of (siteTemplate$ | async)?.chartsData.records"
[categories]="(siteTemplate$ | async)?.chartsData.categories"
[chartData]="record"
></app-pie-chart>
</div>
</div>
<div>{{siteTemplate$ | async | json}}</div>
<div fxLayout="row"
fxLayoutAlign="center"
id="table"
class="app-site-section"
>
<app-table [tableData]="(siteTemplate$ | async)?.tableData"
[dataType]="(siteTemplate$ | async)?.dataType"
></app-table>
</div>
</ng-container>
</div>
如您所见,它由几个依赖于异步管道的子组件组成,图表工作完美,但 table 存在问题。
table.ts
export class TableComponent implements AfterViewInit, OnInit {
@Input() tableData: any = {records: []};
@Input() dataType: any;
dataSource: MatTableDataSource<any> ;
@ViewChild(MatPaginator) paginator: MatPaginator;
@ViewChild(MatSort) sort: MatSort;
constructor() {
}
ngOnInit(): void {
console.log(this.tableData);
this.dataSource = new MatTableDataSource(this.tableData.records);
}
ngAfterViewInit(): void {
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
}
}
在这里我得到一个错误 console.log(this.tableData)
returns null,但是 tableData 在 siteTemplate$
中永远不会为 null 因为我通过添加 tap 和记录此值,它始终显示为对象。
您有多个 siteTemplate$ | async
,每个都会订阅 observable,因此 siteTemplate$ | async
可以是 null
。
为了防止它,只使用一次siteTemplate$ | async
:
<ng-container *ngIf="siteTemplate$ | async as siteTemplate; else other">
...
<app-table [tableData]="siteTemplate.tableData"
[dataType]="siteTemplate.dataType"
></app-table>
</ng-container>
<ng-template #other>
<div fxLayout="row"
fxLayoutAlign="center"
style="margin-top: 60px;">
<mat-spinner></mat-spinner>
</div>
</ng-template>
通过使用异步管道,您不能指望在子组件创建时立即获得异步结果,因为是 异步。
因此,应该在 ngOnChanges 生命周期中监听结果。
ngOnChanges(): void {
console.log(this.tableData);
this.dataSource = new MatTableDataSource(this.tableData.records);
}
我有一个奇怪的案例,我无法通过也不知道它是怎么发生的,所以我得到了名为 SiteComponent
的父组件
这里打字稿逻辑:
ngOnInit(): void {
this.subs.push(
this.route.data.subscribe(data => {
this.siteTemplate$ = this.dataService.getMappedData(`data${data.type}`).pipe(
map(_data => ({..._data, dataType: data.type })),
)
})
);
}
这里是模板文件代码:
<div class="app-site">
<ng-container *ngIf="!siteTemplate$ | async">
<div fxLayout="row"
fxLayoutAlign="center"
style="margin-top: 60px;">
<mat-spinner></mat-spinner>
</div>
</ng-container>
<ng-container *ngIf="siteTemplate$ | async">
<app-filters (filtersChanged)="applyFilters()"></app-filters>
<div class="app-site-section">
<div class="app-site-section-column" id="charts">
<app-linear-chart *ngFor="let record of (siteTemplate$ | async)?.chartsData.records"
[categories]="(siteTemplate$ | async)?.chartsData.categories"
[chartData]="record"
></app-linear-chart>
</div>
<div class="app-site-section-column">
<app-pie-chart *ngFor="let record of (siteTemplate$ | async)?.chartsData.records"
[categories]="(siteTemplate$ | async)?.chartsData.categories"
[chartData]="record"
></app-pie-chart>
</div>
</div>
<div>{{siteTemplate$ | async | json}}</div>
<div fxLayout="row"
fxLayoutAlign="center"
id="table"
class="app-site-section"
>
<app-table [tableData]="(siteTemplate$ | async)?.tableData"
[dataType]="(siteTemplate$ | async)?.dataType"
></app-table>
</div>
</ng-container>
</div>
如您所见,它由几个依赖于异步管道的子组件组成,图表工作完美,但 table 存在问题。
table.ts
export class TableComponent implements AfterViewInit, OnInit {
@Input() tableData: any = {records: []};
@Input() dataType: any;
dataSource: MatTableDataSource<any> ;
@ViewChild(MatPaginator) paginator: MatPaginator;
@ViewChild(MatSort) sort: MatSort;
constructor() {
}
ngOnInit(): void {
console.log(this.tableData);
this.dataSource = new MatTableDataSource(this.tableData.records);
}
ngAfterViewInit(): void {
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
}
}
在这里我得到一个错误 console.log(this.tableData)
returns null,但是 tableData 在 siteTemplate$
中永远不会为 null 因为我通过添加 tap 和记录此值,它始终显示为对象。
您有多个 siteTemplate$ | async
,每个都会订阅 observable,因此 siteTemplate$ | async
可以是 null
。
为了防止它,只使用一次siteTemplate$ | async
:
<ng-container *ngIf="siteTemplate$ | async as siteTemplate; else other">
...
<app-table [tableData]="siteTemplate.tableData"
[dataType]="siteTemplate.dataType"
></app-table>
</ng-container>
<ng-template #other>
<div fxLayout="row"
fxLayoutAlign="center"
style="margin-top: 60px;">
<mat-spinner></mat-spinner>
</div>
</ng-template>
通过使用异步管道,您不能指望在子组件创建时立即获得异步结果,因为是 异步。 因此,应该在 ngOnChanges 生命周期中监听结果。
ngOnChanges(): void {
console.log(this.tableData);
this.dataSource = new MatTableDataSource(this.tableData.records);
}