how to use multiple matSort of Angular material in different tables with different datasouce in the same screen?

125 views Asked by At

I have two tables on the same screen, each one is filled with different datasources and what I want is to add a matSort to each table on all the fields to sort asc or desc

I have it as follows and it works fine in the first table

component.ts

  @ViewChild(MatPaginator) paginator!: MatPaginator;
  @ViewChild(MatSort) sort!: MatSort;
  
  ngOnInit(): void {
    this.obtenerCatalogoProducto();
    this.obtenerCatalogoSubProducto();
  }

 
  dataSource: any;
   obtenerCatalogoProducto() {
    this.catService.obtenerCatProd().subscribe((response) => {
      this.catProducto = response.data;
      console.log('PRUEBA  CAT PROD  ', response.data);
      this.dataSource = new MatTableDataSource(this.catProducto);
      
      this.dataSource.paginator = this.paginator;
      this.dataSource.sort = this.sort;
    });
  }

html I add matSort in tag and mat-sort-header into tag

<form>
        <table mat-table [dataSource]="dataSource" class="mat-elevation-z8" matSort>
          <ng-container matColumnDef="idProducto">
            <th mat-header-cell *matHeaderCellDef mat-sort-header>ID.</th>
            <td mat-cell *matCellDef="let element">{{ element.idProducto }}</td>
          </ng-container>

          <ng-container matColumnDef="descripcionProducto">
            <th mat-header-cell *matHeaderCellDef mat-sort-header>PRODUCTO</th>
            <td mat-cell *matCellDef="let element">
              <mat-form-field>
                <input matInput [value]="element.descripcionProducto" />
              </mat-form-field>
            </td>
          </ng-container>
          <ng-container matColumnDef="botonTipoActions">
            <th mat-header-cell *matHeaderCellDef> ACCIONES </th>
            <td mat-cell *matCellDef="let element">
              <button mat-icon-button color="primary">
                <mat-icon>edit</mat-icon>
              </button>
             
              <button mat-icon-button color="warn" (click)="eliminar($event.target,element)">
                <mat-icon>delete</mat-icon>
              </button>
            </td>
          </ng-container>

          <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
          <tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
        </table>
      </form>
      <mat-paginator [pageSizeOptions]="[5, 10]" showFirstLastButtons aria-label="Select page of periodic elements">
      </mat-paginator>

enter image description here

but when I try to repeat the same on the second table it doesn't work, I did it this way

component.ts

  @ViewChild('sortA') sortA!: MatSort;
  @ViewChild('sortB') sortB!: MatSort;
 
  ngOnInit(): void {
    this.obtenerCatalogoProducto();
    this.obtenerCatalogoSubProducto();
  }

  
  dataSource: any;
   obtenerCatalogoProducto() {
    this.catService.obtenerCatProd().subscribe((response) => {
      this.catProducto = response.data;
      this.dataSource = new MatTableDataSource(this.catProducto);
      this.dataSource.paginator = this.paginator;
      this.dataSource.sort = this.sortA;
    });
  }

  
  dataSourceSubProducto: any;
  private obtenerCatalogoSubProducto() {
    this.catService.obtenerCatSubProd().subscribe((response) => {
      this.catSubProducto = response.data;
      this.dataSourceSubProducto = new MatTableDataSource(this.catSubProducto);
      this.dataSource.sort = this.sortB;
    });
  }

second table

<table mat-table [dataSource]="dataSourceSubProducto" class="mat-elevation-z8" matSort>
        <ng-container matColumnDef="idSubProducto">
          <th mat-header-cell *matHeaderCellDef mat-sort-header>ID.</th>
          <td mat-cell *matCellDef="let element">{{ element.idSubProducto }}</td>
        </ng-container>

        <ng-container matColumnDef="descripcionSubProducto">
          <th mat-header-cell *matHeaderCellDef mat-sort-header>SUBPRODUCTO</th>
          <td mat-cell *matCellDef="let element">
            <mat-form-field>
              <input matInput [value]="element.descripcionSubProducto" />
            </mat-form-field>
          </td>
        </ng-container>


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

but doesnt work, anyone could help me please, what is the way correct

1

There are 1 answers

0
Eliseo On

Disclamer I can not found the answer that solve a similar question (but I rememeber someone answer before)

Angular is not "magic". When we use

@ViewChild(MatPaginator) paginator!: MatPaginator;
@ViewChild(MatSort) sort!: MatSort;

Angular get the first paginator and the first MatSort that found.

If we have two paginators and/or two MatSort (well, when we have two mat-table) we need use two variables. For this we use a template reference variable in .html

<!--see that the first table use the template reference variable "table1"
    idem with paginator-->
<table #table1 mat-table ..>
</table>

<mat-paginator #paginator1 [pageSizeOptions]="[5, 10, 20]"..>
</mat-paginator1>

<!--see that the second table use the template reference variable "table2"
    idem with paginator2-->
<table #table2 mat-table ..>
</table>
<mat-paginator #paginator2 [pageSizeOptions]="[5, 10, 20]"..>
</mat-paginator>
  

Then we can "reach the mat-sort and the mat-paginator using ViewChild. In viewChild we can indicate "what we are looking for" using "{read:...}", see the docs about using selector. This is necessary to reach the "matSort" (but not to reach the paginator)

@ViewChild('table1',{read:MatSort}) sort1: MatSort;
@ViewChild('paginator1') paginator1: MatPaginator;

@ViewChild('table2',{read:MatSort}) sort2: MatSort;
@ViewChild('paginator2') paginator2: MatPaginator;

We can use `{static:true}, if not it's under a *ngIf

@ViewChild('table1',{read:MatSort,static:true}) sort1: MatSort;
@ViewChild('paginator1',{static:true}) paginator1: MatPaginator;

@ViewChild('table2',{read:MatSort,static:true}) sort2: MatSort;
@ViewChild('paginator2',{static:true}) paginator2: MatPaginator;

Then we can use as usual

  //after we define the dataSource and dataSource2
  this.dataSource.sort=this.sort;
  this.dataSource.paginator=this.paginator1;
  this.dataSource2.sort=this.sort2;
  this.dataSource2.paginator=this.paginator2;