如何将 MatTableDataSource 与 observable 一起使用?

Chr*_*ler 20 observable angular-material angular mat-table angular8

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

这个问题的唯一解决方案是在ngOnInit方法中订阅 observable并在新数据到达时始终创建一个新的 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;
        });
}
Run Code Online (Sandbox Code Playgroud)

H3A*_*3A7 37

使用 MatTableDataSource 作为 Observable

你可以只pipe观察到:

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

您可以在模板中的可观察对象上使用异步管道:

[dataSource]="thingsAsMatTableDataSource$ | async"
Run Code Online (Sandbox Code Playgroud)

这样你就不必订阅,仍然可以享受垫表排序等......

防止重复调用构造函数

只需将其实例化为私有成员一次并使用它即可:

private dataSource = new MatTableDataSource<Thing>();

thingsAsMatTableDataSource$: Observable<MatTableDataSource<Thing>>  =
  getThings().pipe(
    map(things => {
      const dataSource = this.dataSource;
      dataSource.data = things
      return dataSource;
}));
Run Code Online (Sandbox Code Playgroud)

这是Stackblitz上的一个简单示例。

  • 谢谢它工作,但不能使用 Observable&lt;MatTableDataSource&lt;Thing&gt;&gt; 可以使用 Observable&lt;any&gt; 错误如下类型 'MatTableDataSource&lt;Service&gt; | null' 不可分配给类型'CdkTableDataSourceInput&lt;Service&gt;'。 (6认同)
  • 这似乎是最简洁、最安全、最惯用的方法,我可以确认它是有效的。我很惊讶它的赞成票这么少。 (4认同)

Stu*_*ows 33

您应该能够MatTableDataSource在类级别更新一次,然后datangOnInit.

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;
    });
}
Run Code Online (Sandbox Code Playgroud)

  • 如果我不想在组件中订阅并在模板中使用 async 来获取数据怎么办? (3认同)
  • 请注意,设置数据后设置排序要慢一些:/sf/answers/3590746211/(在我自己的应用程序中,它没有像链接中那样极端,但仍然产生了显着的变化。 (2认同)

bur*_*suk 7

这是一个解决方法,因为 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();
   }
}
Run Code Online (Sandbox Code Playgroud)

然后在组件中:

dataSource: CustomDataSource;

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

示例:堆栈闪电战