2
votes

Comment obtenir l'instance d'un Mat-Table, si nous avons plusieurs tables dans le composant

Je suis frappé par un problème. J'ai un composant dans Angular 6 où je génère plusieurs Mat-Tables avec des données. J'utilise la boucle ng-for dans la balise div pour parcourir toutes les sources de données Mat-Table. Plus tard, j'essaye d'ajouter une nouvelle ligne à la table. Jusqu'à présent, tout va bien, mais je ne peux pas obtenir l'instance de la table pour laquelle cette fonction Ajouter une ligne est cliquée. Dans .ts fenter le code ici avec l'aide de View-Child, je reçois toujours l'instance de la 1ère table uniquement. Je voudrais obtenir l'instance de toute la table, avec laquelle j'appellerai la fonction de rendu des lignes pour actualiser cette MatTable sélectionnée dans la vue

Exemple de code collé pour la vue et le fichier TS. Remarque L'ajout ne fonctionne pas actuellement.

   <div *ngFor="let data of ViewContent">
<button (click)="addElement(event,data?.tableValues,displayedColumns)">Add element</button> <br />
<table   #testTable mat-table [dataSource]="data?.tableValues">

  <!-- Col1 Column -->
  <ng-container matColumnDef="Col1">
    <th mat-header-cell *matHeaderCellDef> Col1 </th>
    <td mat-cell *matCellDef="let element"> {{element.Col1}} </td>
  </ng-container>

  <!-- Col2 Column -->
  <ng-container matColumnDef="Col2">
    <th mat-header-cell *matHeaderCellDef> Col2 </th>
    <td mat-cell *matCellDef="let element"> {{element.Col2}} </td>
  </ng-container>

  <!-- Col3 Column -->
  <ng-container matColumnDef="Col3">
    <th mat-header-cell *matHeaderCellDef> Col3 </th>
    <td mat-cell *matCellDef="let element"> {{element.Col3}} </td>
  </ng-container>

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



<!-- Copyright 2019 Google Inc. All Rights Reserved.
    Use of this source code is governed by an MIT-style license that
    can be found in the LICENSE file at http://angular.io/license -->

</div>



import {DataSource} from '@angular/cdk/collections';
import {Component,OnInit,ViewChild} from '@angular/core';
import {BehaviorSubject, Observable} from 'rxjs';
import  DalContentdata from 'Content.json';
import { MatTable } from '@angular/material';

@Component({
  selector: 'cdk-table-basic-example',
  styleUrls: ['cdk-table-basic-example.css'],
  templateUrl: 'cdk-table-basic-example.html',
})
export class CdkTableBasicExample implements OnInit  {
   ViewContent: Object;
   displayedColumns: string[] = ['Col1','Col2','Col3'];

  @ViewChild('testTable') table: MatTable<any>;

  ngOnInit() {
    this.ViewContent =  [
    {
      "title":"abc",
      "tableValues": [
        {
          "Col1": "Apple",
          "Col2": "Mango",
          "Col3": "Orange"
        },
        {
          "Col1": "Apple",
          "Col2": "Mango",
          "Col3": "Orange"
        },
        {
          "Col1": "Apple",
          "Col2": "Mango",
          "Col3": "Orange"
        },
        {
          "Col1": "Apple",
          "Col2": "Mango",
          "Col3": "Orange"
        },
        {
          "Col1": "Apple",
          "Col2": "Mango",
          "Col3": "Orange"
        }
      ]
    },
    {
       "title":"abc",
      "displayColumns": "Col1,Col2,Col3",
      "tableValues": [
        {
          "Col1": "Apple",
          "Col2": "Mango",
          "Col3": "Orange"
        },
        {
          "Col1": "Apple",
          "Col2": "Mango",
          "Col3": "Orange"
        },
        {
          "Col1": "Apple",
          "Col2": "Mango",
          "Col3": "Orange"
        },
        {
          "Col1": "Apple",
          "Col2": "Mango",
          "Col3": "Orange"
        },
        {
          "Col1": "Apple",
          "Col2": "Mango",
          "Col3": "Orange"
        }
      ]
    },
    {
       "title":"abc",
      "displayColumns": "Col1,Col2,Col3",
      "tableValues": [
        {
          "Col1": "Apple",
          "Col2": "Mango",
          "Col3": "Orange"
        },
        {
          "Col1": "Apple",
          "Col2": "Mango",
          "Col3": "Orange"
        },
        {
          "Col1": "Apple",
          "Col2": "Mango",
          "Col3": "Orange"
        },
        {
          "Col1": "Apple",
          "Col2": "Mango",
          "Col3": "Orange"
        },
        {
          "Col1": "Apple",
          "Col2": "Mango",
          "Col3": "Orange"
        }
      ]
    }
  ];
  }


  addElement(event, title, tableDataSource, displayColumns) {
        console.log('beforeAdd', tableDataSource);
    tableDataSource.push({
      Col1: 'Test',Col2:'Test',Col3:'Test'
    })
     console.log('afteradd', tableDataSource);
     this.table.renderRows();

    console.log('afteradd', tableDataSource);
  }


}


/**  Copyright 2019 Google Inc. All Rights Reserved.
    Use of this source code is governed by an MIT-style license that
    can be found in the LICENSE file at http://angular.io/license */


9 commentaires

Modifier : pouvez-vous supprimer les codes inutiles et ajouter la fonction que vous utilisez pour ajouter une nouvelle ligne.


Salut Wandrille J'ai supprimé l'ancien code et conservé l'exemple de code. J'espère que cela t'aides.


utilisez @Viewchildren () @ViewChildren () _tables: QueryList alors vous pouvez soit utiliser this._tables.toArray (); faire une boucle


@Roj, merci pour la contribution. this._tables.toArray () me permet d'accéder à toutes les tables. Mais comment appeler les renderRows pour la table requise. Par exemple, disons ceci._tables.toArray () renvoie 4 tables. Et je veux appeler le renderRows () sur la 2ème table, comment faire cela. Cela me donne un résultat indéfini si je le fais. Je veux appeler RenderRows () pour actualiser cette table. Merci d'avance.


@Roj toute aide à ce sujet s'il vous plaît.


@Roj pouvez vous aider sur ma demande pls.merci pour l'entrée. this._tables.toArray () me permet d'accéder à toutes les tables. Mais comment appeler les renderRows pour la table requise. Par exemple, disons ceci._tables.toArray () renvoie 4 tables. Et je veux appeler le renderRows () sur la 2ème table, comment faire cela. Cela me donne un résultat indéfini si je le fais. Je veux appeler RenderRows () pour actualiser cette table. Merci d'avance.


@Massimiliano Sartoretto Toute aide sur celui-ci est également plus utile, merci.


@ k0hamed Pouvez-vous me guider également dans ce numéro


fixe celui-ci sur les lignes inf direction Roj. Nous avons ned pour créer une table d'instance @ViewChildren ('dalTable'): QueryList ; Ensuite, après tout ajout / suppression, nous pouvons rendre les lignes en appelant this.table.toArray (). ForEach (data => data.renderRows ()); Cela rafraîchira toutes les lignes du tableau


4 Réponses :


2
votes

vous devez utiliser ViewChild.

html: supposons que vos tables s'exécutent dans une boucle for avec une variable d'index nommée i:

  ngAfterViewInit() {
//    this.matTable...
  }

ts:

@ViewChild('testTable1') matTable1: MatTable<any>;
  @ViewChild('testTable2') matTable2: MatTable<any>;
  @ViewChild('testTable3') matTable3: MatTable<any>;

ou bien sûr, vous pouvez simplement utiliser un tableau.

n'oubliez pas de l'importer, et vous préférerez utiliser le hook de cycle de vie AfterViewInit

  <table id="testTable{{i}}" [dataSource]="yourDataSource"><!--data source can be set from ts as well-->

Modifier:

si vous souhaitez actualiser votre source de données

this.matTable.dataSource=[...this.data

vous pouvez simplement passer un nouveau tableau ( avec une nouvelle référence) et cela déclenchera le changement de données et votre table de données sera actualisée

Si vous souhaitez créer un identifiant unique pour chaque table en utilisant pour,


8 commentaires

Salut, Merci pour la réponse rapide. Mais cela n'a pas résolu mon problème. Ici, dans l'interface utilisateur, nous aurons 3 tables de tapis avec un bouton Ajouter en haut de chaque table. La condition est que lorsque nous cliquons sur «AJOUTER», un nouvel enregistrement sera ajouté en haut de la table correspondante. Ici, dans mon cas, les enregistrements ont été ajoutés dans la source de données. Cependant, SEULE la 1ère table est actualisée pour afficher l'enregistrement nouvellement ajouté comme j'appelle le renderrows () avec le viewchild. La même chose n'est pas actualisée pour les 2 autres tables car les 2 autres instances de table n'étaient pas sélectionnées.


Le problème principal est dans addElement () comme this.table.renderRows (); Se réfère toujours à la première table UNIQUEMENT. Il ne crée aucune instance pour les autres tables, même si un nouvel enregistrement est ajouté. Par conséquent, la table n'est pas actualisée et l'enregistrement nouvellement ajouté n'est pas affiché.


Salut équipe, toute aide sera appréciée.


Merci Yaacov, le problème est dans le code this.matTable obtient toujours l'instance de la 1ère table uniquement, même si nous avons 3 tables dans l'interface utilisateur. Donc, pour la méthode Add à chaque fois, seule la source de données de la 1ère table est actualisée. Pas le deuxième ou le troisième.


@SantoshShivaKumar avez-vous créé un ViewChild pour chacune des tables en utilisant le bon ID? vous devez créer une instance ViewChild pour chacune de vos tables et y définir la source de données comme vous le souhaitez


Comment faire cela .. Parce que .. Si vous voyez dans mon ode, il n'y aura qu'une seule table qui est présente dans la boucle for.


Équipe HI, toute aide à ce sujet sera utile. J'essaye ceci depuis 4 jours mais je n'arrive pas à résoudre.


Tout le monde a une idée sur celui-ci ... ou dois-je écrire le code en double qui n'est pas correct.



3
votes

J'ai eu un problème similaire et je l'ai résolu en utilisant ViewChildren plutôt que ViewChild.

Au départ, j'avais:

import { MatTable } from "@angular/material/table";

et pour appeler renderRows, j'ai appelé

this.table.first.renderRows();
this.table.last.renderRows();

Cependant, j'avais alors besoin d'une autre table dans le même composant, donc mon code est devenu:

@ViewChildren(MatTable) table !: QueryList<MatTable<string>>;

et

this.table.renderRows();

Avec le premier et le dernier étant des propriétés de queryList. https://angular.io/api/core/QueryList#properties p >

Assurez-vous d'importer MatTable

@ViewChild(MatTable) table: MatTable<string>;


1 commentaires

comment utiliser cela quand nous avons plus de 2 tables?



0
votes

en html:

@ViewChild('table1', { static: true }) table1: MatTable<any>;

dans le modèle:

<table
mat-table
id="table"
class="full-width"
[dataSource]="dataSource"
matSort
data-cy="pg_table"
(matSortChange)="onSortData($event)"
#table1
>


0 commentaires

0
votes

En prolongeant la réponse de Chishty, dans le cas de tables 'n', vous pouvez utiliser @ViewChildren avec une boucle pour appeler renderRows () sur chaque table. Les étapes générales seraient les suivantes -

  1. Importer mat-table

    importer {MatTable} depuis '@ angular / material / table';

  2. Déclarez @ViewChildren avec QueryList

    @ViewChildren (MatTable) csvTable!: QueryList ;

  3. Appelez renderRows lors de l'opération d'ajout ou de suppression

    this.csvTable.toArray (). forEach (data => data.renderRows ());

  4. N'oubliez pas d'utiliser la même variable que table-id dans le modèle

En savoir plus sur @ViewChildren - Angular Docs
En savoir plus sur QueryList - Angular Docs


0 commentaires