MatTable - угловой материал: не удалось найти столбец с идентификатором - PullRequest
0 голосов
/ 17 июня 2019

Я пытаюсь отобразить таблицу «программно»:

<div [formArrayName]="doc.typeSelector">
                  {{ doc.typeSelector }}
</div>
<div *ngIf="documents[doc.typeSelector]">
     <mat-table
      [dataSource]="documents[doc.typeSelector]"
      *ngFor="let col of docColumns">
      <ng-container [matColumnDef]="col">
        <th mat-header-cell *matHeaderCellDef> {{ col | uppercase }} </th>
        <td mat-cell *matCellDef="let element"> {{ element[col] }} </td>
      </ng-container>
    <tr mat-header-row *matHeaderRowDef="docColumns"></tr>
    <tr mat-row *matRowDef="let row; columns: docColumns;"></tr>
  </mat-table>
</div>

Где:

documents: object = {};
docColumns: string[] = ["name", "uploadDate", "uri", "comments"];
docs = [];
docForm: FormGroup;
docTypes: object = {
    fs: 'Financial Statements',
    id: 'Identity Document',
    ad: 'Bank Account Details',
    cd: 'Constitutional Document',
    pd: 'Power Document',
  };

и где переменные documents / docs / docFrom заполняются ngOnInit():

[...] this.docForm = this.fb.group({});
    Object.keys(this.docTypes).map(
      type => {
        this.docForm.addControl(type, this.fb.array([]));
        this.docs.push({
         typeName: this.docTypes[type],
         typeSelector: type
        });
    }
  );

Тогда, если есть клиент, подписка получает данные из базы данных ... и как только мы получаем информацию, она агрегируется в переменные:

// Info for the docForm:
              const cusDocs = this.customer.docRefs;
              Object.keys(cusDocs).map(docType => {
                const currDocs = [];
                cusDocs[docType].forEach(doc => {
                  currDocs.push(this.customerService.createNewDoc(doc));
                });
                const matchForm = this.docForm.get(docType) as FormArray;
                currDocs.forEach(form => {
                  matchForm.push(form);
                });
              });
              Object.keys(this.docForm.value).map(docType => {
                const currForm = this.docForm.get(docType) as FormArray;
                if (currForm.value.length > 0) {
                  Object.keys(currForm.value).map(doc => {
                    const currentDoc = currForm.at(+doc).value;
                    const newDocRow = {
                      name: currentDoc.name,
                      uploadDate: currentDoc.uploadDate,
                      uri: currentDoc.uri,
                      comments: currentDoc.comment
                    };
                    if (!this.documents[docType]) {
                      this.documents[docType] = [];
                    }
                    this.documents[docType].push(newDocRow);
                    console.log(this.documents[docType]);
                  });
                }
              });
              console.log(this.documents);
              console.log(this.docColumns);
  • docs array используется DOM для отображения панели расширения
  • docTypes object используется для построения предыдущей переменной, соответствующей ответу от сервера.Может быть бесполезно, но в то время, когда я создавал это, я хотел убедиться, что информация о сервере соответствует DOM ...
  • docForm - это FormGroup, содержащий 5 различных типов документов, которые могут быть загружены.
  • docColumns - это заранее заданные столбцы displayColumns.
  • И последнее, но не менее важное: documents - это array из object, используемый для определения строк.

Вот что дает console.logs: Logs + error

Я видел похожие вопросы, но я не уверен, что моя ошибка соответствует этим случаям ... Спасибозаранее!

РЕДАКТИРОВАТЬ ---------------------- РЕДАКТИРОВАТЬ: Olipej ответ, кажется, не решить мою проблему, или у меня возникли проблемыпонять, откуда исходит моя ошибка.

Я сделал стекаблиц, воспроизводящий мою структуру данных, и получаю ошибку: https://stackblitz.com/edit/mat-table-error-example

Снимки скриншотов в стеке: enter image description here

Ответы [ 3 ]

2 голосов
/ 18 июня 2019

Ваш цикл ngFor установлен на элемент таблицы mat. Вы хотите использовать цикл в элементе ng-container, чтобы заполнить вашу таблицу данными. Теперь вы генерируете несколько таблиц матов с неверными данными ..

Измените это, и вы увидите, что волшебство случится:)

1 голос
/ 17 июня 2019

Вы уверены, что все объекты, которые вы передаете matTable, имеют свойства, соответствующие идентификаторам столбцов?

В начале шаблона вы проверяете элемент в «документах», но никогда не проверяетеэто свойства.

<div *ngIf="documents[doc.typeSelector]">

Конечно, вам не нужно проверять, существуют ли свойства, но потому что вы получаете сообщение об ошибке: «Не удалось найти столбец с идентификатором« uploadDate »».Передано, на самом деле, есть свойство.

Если это не поможет, не могли бы вы привести пример стекаблиц?

0 голосов
/ 20 июня 2019

Я создаю новый ответ, так как мне нужно будет охватить больше, чем позволяют комментарии.

Прежде всего, вы связали пример стекаблица, который не соответствует коду в вашем вопросе.Ни ваше использование таблицы матов, ни ваши данные, которые вы хотите отобразить.Оба кода по-разному структурированы между кодом в вопросе и кодом в примере.

Я думаю, что сначала вам нужно спросить себя, чего вы хотите достичь.Затем вам нужно спросить себя, что вам нужно для решения проблемы, с которой вы столкнулись.

Теперь, если вы все еще считаете, что использование mat-таблицы - это то, что вам нужно, тогда я помогу вам использовать его с динамическими столбцами.

Для начала mat-table нужен массив объектов для отображения и определение идентификаторов столбцов.

export interface PeriodicElement {
  name: string;
  position: number;
  weight: number;
  symbol: string;
}

const ELEMENT_DATA: PeriodicElement[] = [
  {position: 1, name: 'Hydrogen', weight: 1.0079, symbol: 'H'},
  {position: 2, name: 'Helium', weight: 4.0026, symbol: 'He'},
  {position: 3, name: 'Lithium', weight: 6.941, symbol: 'Li'},
  {position: 4, name: 'Beryllium', weight: 9.0122, symbol: 'Be'},
  {position: 5, name: 'Boron', weight: 10.811, symbol: 'B'},
  {position: 6, name: 'Carbon', weight: 12.0107, symbol: 'C'},
  {position: 7, name: 'Nitrogen', weight: 14.0067, symbol: 'N'},
  {position: 8, name: 'Oxygen', weight: 15.9994, symbol: 'O'},
  {position: 9, name: 'Fluorine', weight: 18.9984, symbol: 'F'},
  {position: 10, name: 'Neon', weight: 20.1797, symbol: 'Ne'},
];

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  displayedColumns: string[] = ['position', 'name', 'weight', 'symbol'];
  dataSource = ELEMENT_DATA;
}

dataSource использует ELEMENT_DATA, который является массивом объектов.

displayedColumns представляет собой строковый массив идентификаторов и является определением каждого столбца.Обратите внимание, что каждая строка в этом массиве должна соответствовать любому из имен свойств / переменных PeriodicElement, с учетом регистра .

И вот как вы используете mat-table.

<table mat-table [dataSource]="dataSource">
  <ng-container *ngFor="let col of displayedColumns" [matColumnDef]="col">
    <th mat-header-cell *matHeaderCellDef> {{col}} </th>
    <td mat-cell *matCellDef="let element"> {{element[col]}} </td>
  </ng-container>

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

mat-table требует источник данных для отображения чего-либо.Обратите внимание, куда я положил * ngFor?Я поместил его в ng-контейнер, потому что один ng-контейнер - это один столбец.Я перебираю displayedColumns.Массив идентификаторов и их использование для получения свойств element.

Вот рабочий пример

Хотя если имена свойств в объектах данных выиспользование никогда не изменится.Вам даже не нужно динамически зацикливать столбцы, и я действительно рекомендую вам просто прочитать стандартную документацию угловой таблицы mat и протестировать пример кода.

Надеюсь, это поможет вам в ваших проблемах.

...