Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple mat-table with MatSort within the same component

I have 2 material 2 tables in the same component with sorting. I cannot find a way to assign the MatSort directive to its own table. I'm only able to use MatSort on the first table and the second table doesn't recognize there is a MatSort on it. Does anyone know how to configure two tables with sorting in the same component?

I've tried defining the ViewChild with different names, but it didn't work.

@ViewChild('hBSort') hBSort: MatSort;
@ViewChild('sBSort') sBSort: MatSort;


this.hBSource = new HBDataSource(this.hBDatabase, this.hBPaginator, 
this.hBSort);
this.sBSource = new SBDataSource(this.sBDatabase, this.sBPaginator, 
this.sBSort);

Table 1
const displayDataChanges = [
   this.hBPaginator.page,
   this.hBSort.sortChange,
   this._filterChange
];

Table 2
const displayDataChanges = [
   this.sBPaginator.page,
   this.sBSort.sortChange,
   this._filterChange
];

Table 1
<mat-table #hBtable [dataSource]="hBSource" matSort style="min-width: 
740px;">
    <ng-container matColumnDef="domain">
        <mat-header-cell *matHeaderCellDef mat-sort-header> {{'list.domain' | translate}} </mat-header-cell>
        <mat-cell *matCellDef="let row"> {{row.domain}} </mat-cell>
    </ng-container>
    <ng-container matColumnDef="general">
        <mat-header-cell *matHeaderCellDef mat-sort-header> {{'list.general' | translate}} </mat-header-cell>
        <mat-cell *matCellDef="let row"> {{row.general.gNum}} ({{row.general.gPct | number: '1.1-2'}}%) </mat-cell>
    </ng-container>
    <mat-header-row *matHeaderRowDef="hBColumns"></mat-header-row>
    <mat-row *matRowDef="let row; columns: hBColumns;"></mat-row>
 </mat-table>


Table 2
<mat-table #sBSort [dataSource]="sBSource" matSort style="min-width: 1200px;">
      <ng-container matColumnDef="domain">
        <mat-header-cell *matHeaderCellDef mat-sort-header> {{'list.domain' | translate}} </mat-header-cell>
        <mat-cell *matCellDef="let row"> {{row.domain}} </mat-cell>
      </ng-container>
      <ng-container matColumnDef="general">
        <mat-header-cell *matHeaderCellDef mat-sort-header> {{'list.general' | translate}} </mat-header-cell>
        <mat-cell *matCellDef="let row"> {{row.general.gNum}} ({{row.general.gPct | number: '1.1-2'}}%) </mat-cell>
      </ng-container>
      <mat-header-row *matHeaderRowDef="sBColumns"></mat-header-row>
      <mat-row *matRowDef="let row; columns: sBColumns;"></mat-row>
</mat-table>
like image 431
Derek J. Avatar asked Nov 13 '17 18:11

Derek J.


3 Answers

The fix to this is that after you define your ViewChild reference in the DOM your need to make sure to add the ="matSort" after it.

Steps:

  1. Set up MatSort instances in your component and define them in your DataSource dependencies like so:

    @ViewChild('hBSort') hBSort: MatSort;
    @ViewChild('sBSort') sBSort: MatSort;
    
    this.hBSource = new HBDataSource(this.hBDatabase, this.hBPaginator, 
    this.hBSort);
    this.sBSource = new SBDataSource(this.sBDatabase, this.sBPaginator, 
    this.sBSort);
    
  2. Define ViewChild References in the DOM and set them equal to matSort (Note: matSort attribute is on the mat-table tag):

    Table 1
    <mat-table #hBSort="matSort" [dataSource]="hBSource" matSort 
      style="min-width: 740px;">
                ***Table Rows and pagination***
    </mat-table>
    
    Table 2
    <mat-table #sBSort="matSort" [dataSource]="sBSource" matSort 
      style="min-width: 1200px;">
                ***Table Rows and pagination***
    </mat-table>   
    
like image 69
Derek J. Avatar answered Oct 30 '22 16:10

Derek J.


In Angular 7, 9 and 10 you need both matSort and the reference #sorter1="matSort":

<table mat-table [dataSource]="ds1" matSort #sorter1="matSort">
</table>
<table mat-table [dataSource]="ds2" matSort #sorter2="matSort">
</table>

Then

@ViewChild('sorter1') sorter1: MatSort;
@ViewChild('sorter2') sorter2: MatSort;


ngOnInit() {
this.ds1.sort = this.sorter1;
this.ds2.sort = this.sorter2;
}
like image 32
TiyebM Avatar answered Oct 30 '22 16:10

TiyebM


I would recommend to create a common component for table which can be used at multiple places in application. As component will create the separate instance of it, mat table did't conflicts there functionality.

In that case you don't need to repeat the code for 2 tables. Below is Table common component you can implement.

Home.component.ts

export class HomeComponent implements OnInit {
  public data1: any[];
  public data2: any[];
  constructor() {
  }
  ngOnInit() {
   this.data1 = [
    {domain: 'Hello1', gNum: 1, gPct: 'table-data1'},
    {domain: 'Hello2', gNum: 2, gPct: 'table-data2'},
    {domain: 'Hello3', gNum: 3, gPct: 'table-data3'},
    {domain: 'Hello4', gNum: 4, gPct: 'table-data4'},
    {domain: 'Hello5', gNum: 5, gPct: 'table-data5'},
    {domain: 'Hello6', gNum: 6, gPct: 'table-data6'},
    {domain: 'Hello7', gNum: 7, gPct: 'table-data7'},
   ];
   this.data2 = [
    {domain: 'Hello1', gNum: 1, gPct: 'table-data1'},
    {domain: 'Hello2', gNum: 2, gPct: 'table-data2'},
    {domain: 'Hello3', gNum: 3, gPct: 'table-data3'},
    {domain: 'Hello4', gNum: 4, gPct: 'table-data4'},
    {domain: 'Hello5', gNum: 5, gPct: 'table-data5'},
    {domain: 'Hello6', gNum: 6, gPct: 'table-data6'},
    {domain: 'Hello7', gNum: 7, gPct: 'table-data7'},
   ]
  }
}

Home.component.html

 <app-table-component [data]='data1'></app-table-component>
 <app-table-component [data]='data2'></app-table-component>

Table.component.ts

@Component({
  selector: 'app-table-component',
  templateUrl: 'table.component.html',
  styleUrls: ['table.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush
})

export class TableComponent implements OnInit, OnChanges {
  @ViewChild(MatPaginator) paginator: MatPaginator;
  @ViewChild(MatSort) sort: MatSort;
  @Input() data: any[];
  public displayedColumns = ['domain', 'gNum', 'gPct'];
  public dataSource: MatTableDataSource<any>;

  constructor() {
  }

  public ngOnInit() {
    setTimeout(() => {
        this.dataSource = new MatTableDataSource(this.data);
        this.dataSource.paginator = this.paginator;
        this.dataSource.sort = this.sort;
   });
  }

  public ngOnChanges(changes: SimpleChanges) {
    this.dataSource = new MatTableDataSource(changes.data.currentValue);
  }

}

Table.component.html

   <mat-table #table [dataSource]="dataSource" matSort  matSortDisableClear matSortDirection="asc">
  <ng-container matColumnDef="domain">
    <mat-header-cell *matHeaderCellDef mat-sort-header>Domain </mat-header-cell>
    <mat-cell *matCellDef="let row"> {{row.domain}} </mat-cell>
  </ng-container>

 <ng-container matColumnDef="gNum">
    <mat-header-cell *matHeaderCellDef mat-sort-header>G Number </mat-header-cell>
    <mat-cell *matCellDef="let row"> {{row.gNum}} </mat-cell>
  </ng-container>

  <ng-container matColumnDef="gPct">
    <mat-header-cell *matHeaderCellDef mat-sort-header>Global Pct </mat-header-cell>
    <mat-cell *matCellDef="let row"> {{row.gPct}} </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 [pageSizeOptions]="[5, 10, 25, 100]"></mat-paginator>
like image 6
Sagar Kharche Avatar answered Oct 30 '22 16:10

Sagar Kharche