Search code examples
angularfirebaseangular-materialangularfire2

material table datasource from firebase


Hi I am using angular material 5 and angular 5 along with angularFirebase2 version 5. I am able to get the datasource and display the material table, but when i am trying to pull the data from the firebase list its not displaying data in the table.

inside my component:

public result;

dataSource = new MatTableDataSource(this.result);

constructor(private db : AngularFireDatabase) {
  this.result = this.db.list('sellEntries').valueChanges();
}
 <div class="example-container mat-elevation-z8">
            <div class="search-bar">
                <mat-form-field>
                    <input matInput (keyup)="applyFilter($event.target.value)" placeholder="Filter">
                </mat-form-field>
                <button mat-raised-button color="primary" (click)="applyFilter('')">All</button>
                <button mat-raised-button color="primary" (click)="applyFilter('india')">India</button>
                <button mat-raised-button color="primary" (click)="applyFilter('south africa')">South Africa</button>
            </div>
                <mat-table #table [dataSource]="dataSource">



                    <ng-container matColumnDef="position">
                        <mat-header-cell *matHeaderCellDef> No. </mat-header-cell>
                        <mat-cell *matCellDef="let element"> {{element.position}} </mat-cell>
                    </ng-container>


                    <ng-container matColumnDef="material">
                        <mat-header-cell *matHeaderCellDef> Name </mat-header-cell>
                        <mat-cell *matCellDef="let element"> {{element.material}} </mat-cell>
                    </ng-container>


                    <ng-container matColumnDef="weight">
                        <mat-header-cell *matHeaderCellDef> Weight </mat-header-cell>
                        <mat-cell *matCellDef="let element"> {{element.weight}} </mat-cell>
                    </ng-container>

                    <ng-container matColumnDef="country">
                        <mat-header-cell *matHeaderCellDef> Symbol </mat-header-cell>
                        <mat-cell *matCellDef="let element"> {{element.country}} </mat-cell>
                    </ng-container>

                    <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
                    <mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
                </mat-table>
            </div>

The table is working and loading data properly if I use component binding. I am looking for a way to load the data source from the Firebase Realtime Database. Thanks in advance


Solution

  • As pointed out in comments, MatTableDataSource's constructor is expecting an array. You should always type variables so your IDE and the build process will let you know about fumblings of this sort. Two ways to go, a) extend the DataSource class:

    class MyDataSource<T> extends DataSource<T> {
        constructor(private observable: Observable<T[]>) {}
        connect() {
            return this.observable;
        }
    }
    // Component: 
    dataSource: MyDataSource<any>;
    ngOnInit() {
        this.dataSource = new MyDataSource(this.db.list('sellEntries').valueChanges());
    }
    

    b) Subscribe and manually set the data:

    destroy$:Subject<void> = new Subject();
    ngOnInit() {
        this.dataSource = new MatTableDataSource([]);
        this.db.list('sellEntries').valueChanges().pipe(
            takeUntil(destroy$); // Complete & cleanup
        ).subscribe(data => this.dataSource.data = data);
    }
    ngOnDestroy() {
        this.destroy$.next();
    }
    

    Personally, I'd go with a) as the class is reusable and makes components leaner.