50 votes

Plusieurs mat-table avec MatSort dans le même composant

J'ai 2 matériaux 2 tables dans le même composant avec tri. Je ne trouve pas de moyen d'attribuer la directive MatSort à sa propre table. Je ne suis capable d'utiliser MatSort que sur la première table et la deuxième table ne reconnaît pas qu'il y a un MatSort dessus. Est-ce que quelqu'un sait comment configurer deux tables avec tri dans le même composant?

J'ai essayé de définir ViewChild avec des noms différents, mais cela n'a pas fonctionné.

@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

         {{'list.domain' | translate}} 
         {{row.domain}} 

         {{'list.general' | translate}} 
         {{row.general.gNum}} ({{row.general.gPct | number: '1.1-2'}}%) 

Table 2

         {{'list.domain' | translate}} 
         {{row.domain}} 

         {{'list.general' | translate}} 
         {{row.general.gNum}} ({{row.general.gPct | number: '1.1-2'}}%)

57voto

Derek J. Points 555

La solution à cela est qu'après avoir défini votre référence ViewChild dans le DOM, vous devez vous assurer d'ajouter ="matSort" après.

Étapes:

  1. Configurer les instances MatSort dans votre composant et les définir dans vos dépendances DataSource comme ceci :

    @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. Définir les références ViewChild dans le DOM et les égaler à matSort (Remarque : l'attribut matSort est sur la balise mat-table) :

    Table 1
    
                ***Table Rows and pagination***
    
    Table 2
    
                ***Table Rows and pagination***

5 votes

Aussi, si l'enfant est caché au démarrage, vous pourriez avoir besoin d'autres astuces, voir github.com/angular/material2/issues/10205

3 votes

Si les tables sont cachées en utilisant *ngIf, alors oui car la référence ViewChild n'existe pas dans le DOM. Si les tables sont cachées en utilisant [hidden], alors cela devrait fonctionner sans aucun problème.

1 votes

Je ne sais pas pourquoi, j'ai essayé plusieurs réponses qui semblaient être les mêmes, et c'est celle qui a fonctionné pour moi. Merci. PS> J'utilise Angular 8.

31voto

TiMr Points 699

Dans Angular 7, 9 et 10, vous avez besoin à la fois de both matSort et de la référence #sorter1="matSort":

Ensuite

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

ngOnInit() {
this.ds1.sort = this.sorter1;
this.ds2.sort = this.sorter2;
}

1 votes

Cela a parfaitement fonctionné pour moi avec Angular 9 aussi. Merci.

1 votes

Fonctionne aussi sur angular 10.

0 votes

Fonctionne comme un charme !!

6voto

George Cs. Points 89

Voici une solution fonctionnelle Angular 6:

import { MatSort, MatTableDataSource } from '@angular/material';

...

@ViewChild('sortCol1') sortCol1: MatSort;
@ViewChild('sortCol2') sortCol2: MatSort;

...

Source de données 1:

this.dataSource1 = new MatTableDataSource(this.dataSource1);
this.dataSource1.sort = this.sortCol1;

Source de données 2:

this.dataSource2 = new MatTableDataSource(this.dataSource2);
this.dataSource2.sort = this.sortCol2;

...

Tableau 1 (Vue):

...

Tableau 2 (Vue):

...

6voto

Sagar Kharche Points 780

Je recommanderais de créer un composant commun pour le tableau qui peut être utilisé à plusieurs endroits dans l'application. Comme le composant va créer une instance séparée de lui-même, le tableau mat ne conflictue pas avec leur fonctionnalité.

Dans ce cas, vous n'avez pas besoin de répéter le code pour 2 tableaux. Ci-dessous se trouve le composant de tableau commun que vous pouvez implémenter.

Home.component.ts

export class HomeComponent implements OnInit {
  public data1: any[];
  public data2: any[];
  constructor() {
  }
  ngOnInit() {
   this.data1 = [
    {domain: 'Bonjour1', gNum: 1, gPct: 'table-data1'},
    {domain: 'Bonjour2', gNum: 2, gPct: 'table-data2'},
    {domain: 'Bonjour3', gNum: 3, gPct: 'table-data3'},
    {domain: 'Bonjour4', gNum: 4, gPct: 'table-data4'},
    {domain: 'Bonjour5', gNum: 5, gPct: 'table-data5'},
    {domain: 'Bonjour6', gNum: 6, gPct: 'table-data6'},
    {domain: 'Bonjour7', gNum: 7, gPct: 'table-data7'},
   ];
   this.data2 = [
    {domain: 'Bonjour1', gNum: 1, gPct: 'table-data1'},
    {domain: 'Bonjour2', gNum: 2, gPct: 'table-data2'},
    {domain: 'Bonjour3', gNum: 3, gPct: 'table-data3'},
    {domain: 'Bonjour4', gNum: 4, gPct: 'table-data4'},
    {domain: 'Bonjour5', gNum: 5, gPct: 'table-data5'},
    {domain: 'Bonjour6', gNum: 6, gPct: 'table-data6'},
    {domain: 'Bonjour7', gNum: 7, gPct: 'table-data7'},
   ]
  }
}

Home.component.html

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;

  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

    Domain 
     {{row.domain}} 

    G Number 
     {{row.gNum}} 

    Global Pct 
     {{row.gPct}}

0 votes

Je suis d'accord que l'utilisation d'un composant est toujours mieux. Dans mon cas, les colonnes de données de chaque tableau étaient très différentes, donc pour ces besoins je n'ai pas créé un composant que chaque tableau pourrait partager. Cependant, je pourrais créer un composant qui a des colonnes dynamiques et des classes de données. Merci pour un autre point de vue!

4voto

Brian Wright Points 320

Modifier :

Je crois que vous avez besoin de :

@ViewChild(MatSort) sort: MatSort;

au-dessus de votre:

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

Ensuite :

ngAfterViewInit() {
    this.hBSource.sort = this.sort;
    this.sBSource.sort = this.sort;
  }

En supposant que votre HBDataSource et SBDataSource exportent tous les deux MatTableDataSource();

Je fais référence à ces sources :

https://material.angular.io/components/sort/overview https://github.com/angular/material2/blob/master/src/demo-app/table/table-demo.ts

0 votes

Ne créerait-on pas simplement une autre référence à une directive de tri, car @ViewChild (MatSort) sort: MatSort; fait simplement référence à la table mat avec l'attribut matSort dessus. J'ai essayé, mais ça n'a pas fonctionné :(

0 votes

Ah, désolé, c'est ma faute. Il semble que ce que j'ai dit nécessite que vous modifiez la façon dont vous appliquez le tri aux tableaux. Je faisais référence à ceci : material.angular.io/components/sort/overview. Peut-être que cela pourrait vous aider. Il y a aussi cette démo : github.com/angular/material2/blob/master/src/demo-app/table/‌…

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X