Estoy usando mat-table y estoy tratando de usar MatTableDataSource con un observable (obtengo los datos de un servicio web), pero no sé cómo configurar MatTableDataSource para usar un observable en lugar de una matriz.
¿La única solución a este problema es suscribirse a lo observable en el método ngOnInit y crear siempre un nuevo MatTableDataSource cuando lleguen nuevos datos?
Esto es lo que tengo hasta ahora, pero no sé si esta es la solución correcta para trabajar con MatTableDataSource con un observable.
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; }); }También puedes usar un observable, solo (*)
[dataSource]="dataSource|async"(*) realmente no necesitas usar la tubería asíncrona
Vea un ejemplo en stackblitz , donde reemplazo el primer ejemplo del documento por
dataSource = of(ELEMENT_DATA).pipe(delay(1000));He lanzado una biblioteca para eso: @matheo/datasource
Te explico los conceptos básicos en este artículo:
https://medium.com/@matheo/reactive-datasource-for-angular-1d869b0155f6
y en el código de ejemplo, puede ver cómo obtengo elementos de una base de datos de Firebase y manipulo la paginación. clasificación y filtros en el repositorio de ejemplo
Espero que os guste y me deis vuestra opinión al respecto ;)
Debería poder actualizar MatTableDataSource una vez en el nivel de clase y luego usar el configurador de data en ngOnInit .
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; }); }esta es una solución, porque MatTableDataSource no es compatible con Observable como fuente de datos
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(); } }luego en componente:
dataSource: CustomDataSource; ngOnInit(): void { const observableData$ = getData(); this.dataSource = new CustomDataSource(observableData$); // this.dataSource.sort = this.sort; // add sorting or filter }ejemplo: stackblitz
Puedes pipe tu observable:
thingsAsMatTableDataSource$: Observable<MatTableDataSource<Thing>> = getThings().pipe( map(things => { const dataSource = new MatTableDataSource<Thing>(); dataSource.data = things; return dataSource; }));Como se mencionó anteriormente, puede usar una tubería asíncrona en su observable en la plantilla como fuente de datos:
[dataSource]="thingsAsMatTableDataSource$ | async"De esta manera, no tiene que suscribirse y aún puede disfrutar de la clasificación de tapetes, etc.