How to use the MatTableDataSource with an observable?

Use MatTableDataSource as Observable

You can just pipe your observable:

thingsAsMatTableDataSource$: Observable<MatTableDataSource<Thing>>  =
    map(things => {
      const dataSource = new MatTableDataSource<Thing>(); = things;
      return dataSource;

You can use an async pipe on your observable in the template:

[dataSource]="thingsAsMatTableDataSource$ | async"

This way you do not have to subscribe, and can still enjoy mat-table sorting etc...

Prevent Repeated Constructor Calls

Just instantiate it once as a private member and use that instead:

private dataSource = new MatTableDataSource<Thing>();

thingsAsMatTableDataSource$: Observable<MatTableDataSource<Thing>>  =
    map(things => {
      const dataSource = this.dataSource; = things
      return dataSource;

Here's a simple example on Stackblitz.

this is a workaround, because MatTableDataSource doesn't support Observable as data source

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[]>) {
        this.collection$ = collection.subscribe(data => {
  = data; // here you have to adjust the behavior as needed

   disconnect() {

then in component:

dataSource: CustomDataSource;

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

example: stackblitz

You can use an observable too, just (*)


(*) really you needn't use the pipe async

See an example in stackblitz, where I replace the first example of the doc by

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

You should be able to new up the MatTableDataSource once at the class level and then use the data setter in ngOnInit.

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

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