如何将 MatTableDataSource 与可观察对象一起使用?

How to use the MatTableDataSource with an observable?

我正在使用 mat-table 并且我正在尝试将 MatTableDataSource 与可观察对象一起使用(我从 Web 服务获取数据),但是我不知道如何配置 MatTableDataSource 以使用可观察对象而不是数组。

这个问题的唯一解决方案是在 ngOnInit 方法中订阅可观察对象,并在新数据到达时始终创建一个新的 MatTableDataSource 吗?

这是我到目前为止所拥有的,但我不知道这是否是使用带有可观察对象的 MatTableDataSource 的正确解决方案。

dataSource: MatTableDataSource<Thing>;
@ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
@ViewChild(MatSort, { static: true }) sort: MatSort;

ngOnInit() {
    getThings().subscribe(things => {
        this.dataSource = new MatTableDataSource(things);
        this.dataSource.paginator = this.paginator;
        this.dataSource.sort = this.sort;
        });
}

你也可以使用 observable,只是 (*)

[dataSource]="dataSource|async"

(*) 你真的不需要使用管道异步

查看 stackblitz 中的示例,我将文档的第一个示例替换为

dataSource = of(ELEMENT_DATA).pipe(delay(1000));

我为此发布了一个库:@matheo/datasource

我在这篇文章中解释基本概念:
https://medium.com/@matheo/reactive-datasource-for-angular-1d869b0155f6

在示例代码中,您可以看到我如何从 Firebase 数据库中获取项目并操作分页。示例 repo
中的排序和过滤器 我希望你喜欢它并给我你的意见 ;)

您应该可以在 class 级别更新 MatTableDataSource 一次,然后在 ngOnInit 中使用 data setter。

dataSource = new MatTableDataSource<Thing>();
@ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
@ViewChild(MatSort, { static: true }) sort: MatSort;

ngOnInit() {
    getThings().subscribe(things => {
        this.dataSource.data = things;
        this.dataSource.paginator = this.paginator;
        this.dataSource.sort = this.sort;
    });
}

这是一种解决方法,因为 MatTableDataSource 不支持 Observable 作为数据源

import { MatTableDataSource } from '@angular/material';
import { Observable, Subscription } from 'rxjs';
import { SomeInterface} from './some.interface';

export class CustomDataSource extends MatTableDataSource<SomeInterface> {

    private collection: SomeInterface[] = [];

    private collection$: Subscription;

    constructor(collection: Observable<SomeInterface[]>) {
        super();
        this.collection$ = collection.subscribe(data => {
           this.data = data; // here you have to adjust the behavior as needed
        });
    }

   disconnect() {
     this.collection$.unsubscribe();
     super.disconnect();
   }
}

然后在组件中:

dataSource: CustomDataSource;

ngOnInit(): void {
  const observableData$ = getData();
  this.dataSource = new CustomDataSource(observableData$);
  // this.dataSource.sort = this.sort; // add sorting or filter
}

示例:stackblitz

要将 MatTableDataSource 用作 Observable:

你可以 pipe 你的 observable:

thingsAsMatTableDataSource$: Observable<MatTableDataSource<Thing>>  =
  getThings().pipe(
    map(things => {
      const dataSource = new MatTableDataSource<Thing>();
      dataSource.data = things;
      return dataSource;
}));

如上所述,您可以在模板中的可观察对象上使用异步管道作为数据源:

[dataSource]="thingsAsMatTableDataSource$ | async"

这样你就不用订阅了,仍然可以享受mat-table排序等...