我正在使用带排序的角度材料表https://stackblitz.com/run?file=src%2Fapp%2Ftable-sorting-example.ts
我计划将其用作可重用组件,以便在父组件上,我只需要传递列和数据源,如
<app-reports-mat-table [columns]="columns" [dataSource]="dataSource"></app-reports-mat-table>
如果我检查数据源设置为
<app-reports-mat-table *ngIf="dataSource" [columns]="columns" [dataSource]="dataSource"></app-reports-mat-table>
,它根本不会显示任何内容。
请建议如何正确地将数据源传递给子组件,或者如何将其变成可重用的组件?谢谢你
父模板
<app-reports-mat-table [columns]="columns" [dataSource]="dataSource"></app-reports-mat-table>
家长ts
export interface FundingNeeds {
pdoName: string;
pdoIdentifiedAdvocacy?: string;
program?: string;
yearProposed?: string;
unitOfItem?: string;
location?: string;
}
@Component({
selector: 'app-report-funding-needs',
templateUrl: './report-funding-needs.component.html',
styleUrls: ['./report-funding-needs.component.css'],
})
export class ReportFundingNeedsComponent {
dataSource: MatTableDataSource<FundingNeeds>;
columns = [
{
columnDef: 'pdoName',
header: 'PDO Name',
cell: (element: FundingNeeds) => `${element.pdoName}`,
},
{
columnDef: 'pdoIdentifiedAdvocacy',
header: 'PDO Identified Advocacy',
cell: (element: FundingNeeds) => `${element.pdoIdentifiedAdvocacy}`,
},
{
columnDef: 'program',
header: 'Program',
cell: (element: FundingNeeds) => `${element.program}`,
},
{
columnDef: 'yearProposed',
header: 'Year Proposed',
cell: (element: FundingNeeds) => `${element.yearProposed}`,
},
{
columnDef: 'unitOfItem',
header: 'Unit of Main Item to Procure/Build',
cell: (element: FundingNeeds) => `${element.unitOfItem}`,
},
{
columnDef: 'location',
header: 'Location',
cell: (element: FundingNeeds) => `${element.location}`,
},
];
lastEntry = new Date();
constructor(private reportFundingNeedsService: ReportFundingNeedsService) {}
ngOnInit(): void {
this.reportFundingNeedsService
.getFundingNeedsSummary()
.pipe(take(1))
.subscribe((response: any) => {
// Parse the response and transform it into FundingNeeds array
const fundingNeedsData: FundingNeeds[] = [];
response.results.pdos.forEach(pdo => {
pdo.pdo_advocacies.forEach(advocacy => {
advocacy.pdo_programs.forEach(program => {
fundingNeedsData.push({
pdoName: pdo.name,
pdoIdentifiedAdvocacy: advocacy.advocacy,
program: program.program,
yearProposed: program.proposed_date,
unitOfItem: program.admin_beneficiary_category ? program.admin_beneficiary_category.category : '',
location:
program.pdo_program_locations.length > 0 ? program.pdo_program_locations[0].location.name : '',
});
});
});
});
// Assign the data array to MatTableDataSource
this.dataSource = new MatTableDataSource<FundingNeeds>(fundingNeedsData);
});
}
}
子模板
<table mat-table [dataSource]="dataSource" matSort (matSortChange)="announceSortChange($event)"
class="mat-elevation-z8">
<ng-container *ngFor="let column of columns" [matColumnDef]="column.columnDef">
<th mat-header-cell *matHeaderCellDef mat-sort-header sortActionDescription="Sort by {{ column.header }}">
{{column.header}}
</th>
<td mat-cell *matCellDef="let row">
{{column.cell(row)}}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
儿童ts
export class ReportsMatTableComponent implements AfterViewInit, OnInit {
@Input() columns: {
columnDef: string;
header: string;
cell: (element: any) => string;
}[] = [];
@Input() dataSource: MatTableDataSource<any>;
displayedColumns: string[];
constructor(private _liveAnnouncer: LiveAnnouncer) {}
@ViewChild(MatSort) sort: MatSort;
ngOnInit(): void {
if (this.columns) {
this.displayedColumns = this.columns.map(c => c.columnDef);
}
}
ngAfterViewInit() {
console.log(this.dataSource);
if (this.dataSource) {
console.log("child has data");
this.dataSource.sort = this.sort;
}
}
/** Announce the change in sort state for assistive technology. */
announceSortChange(sortState: Sort) {
// This example uses English messages. If your application supports
// multiple language, you would internationalize these strings.
// Furthermore, you can customize the message to add additional
// details about the values being sorted.
if (sortState.direction) {
this._liveAnnouncer.announce(`Sorted ${sortState.direction}ending`);
} else {
this._liveAnnouncer.announce('Sorting cleared');
}
}
}
我注意到,当我单击类似
<mat-select>
之类的内容时,在父组件上表格中会填充数据。
所以我认为这个问题与角度的变化检测有关。因此我检查了子组件,然后是父组件,最后在布局组件中找到了罪魁祸首:
import { ChangeDetectionStrategy, Component } from '@angular/core';
@Component({
selector: 'app-report-layout',
templateUrl: './report-layout.component.html',
styleUrls: ['./report-layout.component.css'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ReportLayoutComponent { }
删除
changeDetection: ChangeDetectionStrategy.OnPush
后,我的可重用组件 <app-reports-mat-table *ngIf="dataSource" [columns]="columns" [dataSource]="dataSource"></app-reports-mat-table>
现在显示表格数据。