Angular Material mat-table数据未从父更改

时间:2018-02-26 14:52:59

标签: angular-material2

我在组件mat-table中使用MatTableDataSource,我想从其父组件设置数据,但数据不会在屏幕上刷新,而子组件则检测到数据更改。

子组件

@Component({
  selector: 'app-person-list',
  template: `
    <mat-table #table [dataSource]="dataSource">
      <ng-container matColumnDef="name">
        <mat-header-cell *matHeaderCellDef> Name </mat-header-cell>
        <mat-cell *matCellDef="let person">{{ person.name }}</mat-cell>
      </ng-container>
      <ng-container matColumnDef="age">
        <mat-header-cell *matHeaderCellDef> Age </mat-header-cell>
        <mat-cell *matCellDef="let person">{{ person.age }}</mat-cell>
      </ng-container>

      <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
      <mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
    </mat-table>
  `
})
export class PersonListComponent implements OnInit, OnChanges {
  @Input() data: Person[];

  displayedColumns = ['name', 'age'];
  dataSource = new MatTableDataSource<Person>();

  ngOnInit() {
    this.dataSource.data = this.data;
  }

  ngOnChanges(changes) {
    console.log('Data changed', this.data);
  }
}

父组件

@Component({
  selector: 'app',
  template: `<app-person-list [data]="personList"></app-person-list>`
})
export class AppComponent implements OnInit {
  personList: Person[] = [];

  constructor(private service: PersonService) {
  }

  ngOnInit() {
    this.service.getPersonList().subscribe(res => this.personList.push(...res));
  }
}

Plunker

有人知道数据更改时表格未更新的原因吗?提前谢谢!

2 个答案:

答案 0 :(得分:3)

问题是你只在ngOnInit上调用this.dataSource.data = this.data;,这意味着你没有对更新的数据做任何事情。

我为此创建了一个管道,因此我不必在任何地方使用MatTableDataSource -

@Pipe({
   name: 'dataSource'
})
export class DataSourcePipe implements PipeTransform {
  transform(array: any[]): any {
    return array ? new MatTableDataSource(array) : new MatTableDataSource([]);
  }
}

在模板中使用它$data | dataSource

这样您的数据始终是最新的,您不必手动使用MatTableDataSource。

编辑: 使用此功能时,您仍然可以使用过滤器和排序功能。

您正在为组件提供数据,然后使用MatTableDataSource来包装它。相反,你可以这样做 - <component [data]="$array | async | dataSource"></component>其中$ array是一个可观察的。

然后在组件内部 - <mat-table [dataSource]="data"></mat-table>

这样您就可以操作数据对象,而无需将其包装在组件内的MatTableDataSource中。

答案 1 :(得分:2)

我发现的唯一方法是更改​​数组的引用并重新分配...

子组件

@Component( [...] )
export class PersonListComponent implements OnChanges {
  @Input() data: Person[];

  displayedColumns = ['name', 'age'];
  dataSource = new MatTableDataSource<Person>();

  ngOnChanges(changes) {
    this.dataSource.data = this.data;
  }
}

父组件

@Component( [...] )
export class AppComponent implements OnInit {
  personList: Person[] = [];

  constructor(private service: PersonService) {
  }

  ngOnInit() {
    this.service.getPersonList().subscribe(res => {
      if (this.personList.length > 0) {
        res.unshift(this.personList);
      }
      this.personList = res;
    });
  }
}