Angular material table not showing data

2020-08-26 10:51发布

People who want paging and sorting on client side please refer this link

Here is what I tried. The data is loading in the console. but it is not displayed on the grid or mat table.

I don't have any error in the console. I am able to see the data in the console but the data is not loaded into the grid.

Can somebody tell me what am I doing wrong?

The actual database from where data is emitted out.

export class FormsDatabase {

   formsList =  new BehaviorSubject([]);
    get data(){

      return this.formsList.value;
   }

 constructor(private _formsServicedata: FormsService){
    this._formsServicedata.getAllFormData('').subscribe((form)=>{
        console.log("Form DataSource: ");
    this.formsList.next(form);
  })
   }

}


export class FormDataSource extends DataSource<any>{

    constructor( private formsDb: FormsDatabase,public 
    paginator:MatPaginator , public sort: MatSort
    ) {
       super()        
      }

   connect():Observable<any>{
      const formsData=[
         this.formsDb.formsList ,
         this.sort.sortChange
    ];

     return Observable.merge(...formsData).map(()=>{
          this.getSortedData();
    })


    }

Sort Function to sort the data

      getSortedData(){

        const data = this.formsDb.data.slice();
       if(!this.sort.active || this.sort.direction==''){ return data;}

        return data.sort((a,b)=>{

        let propertyA:number|string='';
        let propertyB:number|string='';

    switch(this.sort.active)
    {
        case 'formname': [propertyA,propertyB]=
     [a.formname,b.formname];break;
        case 'displaytext': [propertyA,propertyB]=
     [a.displaytext,b.displaytext];break;
        case 'sortorder': [propertyA,propertyB]=
     [a.sortorder,b.sortorder];break;
    }

    let valueA = isNaN(+propertyA) ? propertyA : +propertyA;
    let valueB = isNaN(+propertyB) ? propertyB : +propertyB;

    return (valueA < valueB?-1:1)*(this.sort.direction=='asc'?1:-1);
   });
  }

       disconnect() { }

 }

HTML

  <mat-table #table [dataSource]="dataSource" matSort>

      <ng-container matColumnDef="formname">
        <mat-header-cell *matHeaderCellDef mat-sort-header> FORM NAME 
     </mat-header-cell>
          <mat-cell *matCellDef="let element"> {{element.formname}} 
    </mat-cell>
      </ng-container>


      <ng-container matColumnDef="displaytext">
        <mat-header-cell *matHeaderCellDef mat-sort-header> DISPLAY TEXT </mat-header-cell>
        <mat-cell *matCellDef="let element"> {{element.displaytext}} </mat-cell>
      </ng-container>

      <ng-container matColumnDef="sortorder">
            <mat-header-cell *matHeaderCellDef mat-sort-header> SORT ORDER</mat-header-cell>
            <mat-cell *matCellDef="let element"> {{element.sortorder}} </mat-cell>
      </ng-container>

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

    <mat-paginator #paginator
                   [pageSize]="10"
                   [pageSizeOptions]="[5, 10, 20]"
                   [showFirstLastButtons]="true">
    </mat-paginator>
  </div>

Service:

Forms Service has the below method which returns the forms list as observable

  getAllFormData(orderBy:string) {
    return this.af.list('/forms');
  }

4条回答
趁早两清
2楼-- · 2020-08-26 11:34

I reproduce your code and just like you I can't make it works as the examples provided by angular material team but I used a workaround to make the sort function works.

 export class FormDataSource extends DataSource<any> {

      constructor(private formsDb: FormsDatabase, public paginator: MatPaginator, 
        public sort: MatSort) {
        super();
        this.sort.sortChange.subscribe(t => 
          this.formsDb.formsList.next(this.getSortedData()));
      }

      connect(): Observable<any[]> {
        return this.formsDb.formsList;
      }
        getSortedData () {
          const data = this.formsDb.data.slice();
          if (!this.sort.active || this.sort.direction === '') {
            return data;
          }
          return data.sort((a, b) => {

            let propertyA: number | string = '';
            let propertyB: number | string = '';

            switch (this.sort.active) {
              case 'formname':
                [propertyA, propertyB] =
                  [a.formname, b.formname];
                break;
              case 'displaytext':
                [propertyA, propertyB] =
                  [a.displaytext, b.displaytext];
                break;
              case 'sortorder':
                [propertyA, propertyB] =
                  [a.sortorder, b.sortorder];
                break;
            }

            const valueA = isNaN(+propertyA) ? propertyA : +propertyA;
            const valueB = isNaN(+propertyB) ? propertyB : +propertyB;

            return (valueA < valueB ? -1 : 1) * (this.sort.direction == 'asc' ? 1 : -1);
          });
        }

        disconnect() {
        }
      }

After view init

enter image description here

After applying the filter

enter image description here

查看更多
劫难
3楼-- · 2020-08-26 11:36

Add an ngIf="dataSource" in the <mat-table> tag.

This problem occurs if the data is asynchronous. the DOM is getting loaded before the data is fetched.

Check the dataSource before rendering the DOM.

查看更多
放荡不羁爱自由
4楼-- · 2020-08-26 11:39

This problem happens due to the way angular detects changes, which sometimes doesn't happen and no re-render is triggered.

To solve this, import ChangeDetectorRef from '@angular/core', inject it in the component constructor (cd: ChangeDetectorRef), then use it after sorting the data:

return Observable.merge(...formsData).map(()=>{
  this.getSortedData();
  this.cd.detectChanges(); // or this.cd.markForCheck() if detectChanges does not work.
})
查看更多
女痞
5楼-- · 2020-08-26 11:44

From the example https://material.angular.io/components/table/overview You should remove the tr element from it. Wrong implementation:

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

Correct Implementation:

<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
查看更多
登录 后发表回答