Как получить экземпляр Mat-таблицы, если у нас есть несколько таблиц в компоненте

#angular #mat-table

#angular #mat-таблица

Вопрос:

Я столкнулся с некоторой проблемой. У меня есть компонент в Angular 6, где я генерирую несколько Mat-таблиц с данными. Я использую цикл ng-for в теге div для перебора всех источников данных Mat-таблицы. Позже я пытаюсь добавить новую строку в таблицу. Пока все в порядке, но я не могу получить экземпляр таблицы, для которой нажата эта функция добавления строки. В .ts fenter code hereile с помощью View-Child я всегда получаю экземпляр только 1-й таблицы. Я хотел бы получить экземпляр всей таблицы, с помощью которого я вызову функцию render rows, чтобы обновить эту выбранную таблицу соответствия в представлении

Вставил пример кода для представления и TS-файла. Примечание. Добавление сейчас не работает.

    <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 */
  

Комментарии:

1. Редактировать : Можете ли вы удалить ненужные коды и добавить функцию, которую вы используете для добавления новой строки.

2. Привет, Wandrille, я удалил старый код и сохранил тот же исходный код. Надеюсь, это поможет.

3. используйте @Viewchildren() @ViewChildren() _tables: список запросов<любой> , затем вы можете либо использовать this._tables . toArray(); для перебора

4. @Roj, спасибо за ввод. this._tables. toArray () дает мне доступ ко всем таблицам. Но как вызвать renderRows для требуемой таблицы. Например, давайте скажем это._tables. toArray() возвращает 4 таблицы. И я хочу вызвать renderRows () во 2-й таблице, как это сделать. Это дает мне результат как неопределенный, если я это делаю. Я хочу вызвать RenderRows (), чтобы обновить эту таблицу. Заранее спасибо.

5. @Roj любая помощь по этому вопросу, пожалуйста.

Ответ №1:

У меня была похожая проблема, и я решил ее, используя ViewChildren вместо ViewChild .

Изначально у меня был:

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

и чтобы вызвать renderRows для нее, я вызывал

 this.table.renderRows();
  

Однако затем мне понадобилась другая таблица в том же компоненте, поэтому мой код изменился на:

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

и

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

Где first и last являются свойствами QueryList.
https://angular.io/api/core/QueryList#properties

Убедитесь, что вы импортируете MatTable

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

Комментарии:

1. как мы должны использовать это, когда у нас более 2 таблиц?

Ответ №2:

вы должны использовать ViewChild.

html: давайте предположим, что ваши таблицы выполняются внутри цикла for с индексной переменной с именем i:

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

ts:

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

или, конечно, можно просто использовать массив.

не забудьте импортировать ее, и вы предпочтете использовать AfterViewInit — хук жизненного цикла

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

Редактировать:

если вы хотите обновить свой источник данных

this.matTable.DataSource=[…this.data]

вы можете просто передать новый массив (с новой ссылкой), и это вызовет изменение данных, и ваша таблица данных обновится

Если вы хотите создать unic ID для каждой таблицы, используя для,

Комментарии:

1. Привет, спасибо за быстрый ответ. Но это не решило мою проблему. Здесь, в пользовательском интерфейсе, у нас будет 3 Mat-таблицы с кнопкой Добавить вверху каждой таблицы. Требование заключается в том, что когда мы нажимаем «ДОБАВИТЬ», новая запись будет добавлена в верхней части соответствующей таблицы. Здесь в моем случае записи были добавлены в источник данных. Однако обновляется ТОЛЬКО 1-я таблица, чтобы показать недавно добавленную запись, поскольку я вызываю renderrows() с viewchild. То же самое не обновляется для других 2 таблиц, поскольку другие 2 экземпляра таблицы не были выбраны.

2. Основная проблема заключается в addElement(), подобном this.table.renderRows(); Всегда ссылается ТОЛЬКО на первую таблицу . Это не создает никаких экземпляров для других таблиц, хотя добавляется новая запись. В результате таблица не обновляется, и вновь добавленная запись не отображается.

3. Привет, команда, любая помощь будет оценена.

4. Спасибо Yaacov, проблема в коде this.matTable всегда получает экземпляр только 1-й таблицы, даже если у нас есть 3 таблицы в пользовательском интерфейсе. Таким образом, для метода Add каждый раз обновляется только источник данных 1-й таблицы. Не вторая или третья.

5. @SantoshShivaKumar вы создали ViewChild для каждой из таблиц, используя правильный идентификатор? вам нужно создать экземпляр ViewChild для каждой из ваших таблиц и установить там источник данных по своему усмотрению

Ответ №3:

Продолжая ответ Чишти, в случае ‘n’ таблиц, вы можете использовать @ViewChildren с циклом для вызова renderRows() для каждой таблицы. Общие шаги будут следующими —

  1. Импорт mat-table

    импортируйте { MatTable } из ‘@angular/material /table’;

  2. Объявляем @ViewChildren с QueryList

    @ViewChildren(MatTable) csvTable !: список запросов<MatTable>;

  3. Вызов renderRows операции добавления или удаления

    this.csvTable.toArray().forEach(данные => data.renderRows());

  4. Не забудьте использовать ту же переменную, что и table-id в шаблоне

    <mat-таблица #csvTable [Источник данных]=»csvForm.value»>

Подробнее о @ViewChildren Angular Docs

Подробнее о QueryList Angular Docs

Ответ №4:

в html:

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

в шаблоне:

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