如何将数据从父组件传递到角度材料表子组件?

问题描述 投票:0回答:1

我正在使用带排序的角度材料表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');
    }
  }
}
angular typescript angular-material angular-material-table
1个回答
0
投票

我注意到,当我单击类似

<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>
现在显示表格数据。

© www.soinside.com 2019 - 2024. All rights reserved.