Angular 提供了重复的列名:角度材质数据表

Angular 提供了重复的列名:角度材质数据表,angular,typescript,angular-material,angular7,angular8,Angular,Typescript,Angular Material,Angular7,Angular8,出于某种原因,我在为数据表创建复选框列时出错 我从控制台了解错误,但我能做些什么来修复它 view.component.html <mat-card-content> <div class="view-container mat-elevation-z8"> <table mat-table [dataSource]="dataSource" matSort> <ng-container matColumnDef="column" *ngF

出于某种原因,我在为数据表创建复选框列时出错

我从控制台了解错误,但我能做些什么来修复它

view.component.html

<mat-card-content>
<div class="view-container mat-elevation-z8">
  <table mat-table [dataSource]="dataSource" matSort>

    <ng-container matColumnDef="column" *ngFor="let column of displayedColumns">
      <th mat-header-cell *matHeaderCellDef>
        <mat-checkbox (change)="$event ? masterToggle() : null"
                      [checked]="selection.hasValue() && isAllSelected()"
                      [indeterminate]="selection.hasValue() && !isAllSelected()">
        </mat-checkbox>
      </th>
      <td mat-cell *matCellDef="let action">
        <mat-checkbox (click)="$event.stopPropagation()"
                      (change)="$event ? selection.toggle(row) : null"
                      [checked]="selection.isSelected(row)">
        </mat-checkbox>
      </td>
    </ng-container>

    <ng-container [matColumnDef]="column" *ngFor="let column of displayedColumns">
      <th mat-header-cell *matHeaderCellDef mat-sort-header>
        {{ column }}
        <mat-icon aria-hidden="false" aria-label="filter icon">more_horiz</mat-icon>
      </th>
      <td mat-cell *matCellDef="let action">{{ action[column] }}
      </td>
    </ng-container>

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

  <mat-paginator [pageSizeOptions]="pageSizeOptions" showFirstLastButtons></mat-paginator>
</div>
<mat-card-content>
<div class="view-container mat-elevation-z8">
  <table mat-table [dataSource]="dataSource" matSort>

    <ng-container matColumnDef="select">
      <th mat-header-cell *matHeaderCellDef>
        <mat-checkbox (change)="$event ? masterToggle() : null"
                      [checked]="selection.hasValue() && isAllSelected()"
                      [indeterminate]="selection.hasValue() && !isAllSelected()">
        </mat-checkbox>
      </th>
      <td mat-cell *matCellDef="let row">
        <mat-checkbox (click)="$event.stopPropagation()"
                      (change)="$event ? selection.toggle(row) : null"
                      [checked]="selection.isSelected(row)">
        </mat-checkbox>
      </td>
    </ng-container>

    <ng-container [matColumnDef]="column" *ngFor="let column of displayedColumns | slice:1 ">
      <th mat-header-cell *matHeaderCellDef mat-sort-header>
        {{ column }}
        <mat-icon aria-hidden="false" aria-label="filter icon">more_horiz</mat-icon>
      </th>
      <td mat-cell *matCellDef="let action">{{ action[column] }}
      </td>
    </ng-container>

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

  <mat-paginator [pageSizeOptions]="pageSizeOptions" showFirstLastButtons></mat-paginator>
</div>

您之所以会收到错误,是因为您在
displayedColumns
上循环了两次

要修复错误,您需要:

  • 修正“选择”列的定义
  • 从显示的列中排除您的select列id,以防止多次使用它
  • 在行定义的id列表中包括select列id
选择列


如果只想显示一个select列,并且每行都有一个复选框,则需要在此处删除
*ngFor=“…”
。 如果需要多个select列(例如,每个数据列一个),则需要为这些列定义一个唯一ID列表并在其上循环:


其他列

displayedColumns: string[] = [];

const displayedColumns = this.viewData.Columns.map((c: { Name: any; }) => c.Name);
    displayedColumns[2] = 'Folder1';
    this.displayedColumns = displayedColumns;
    // tslint:disable-next-line: max-line-length
    const fetchedData = this.viewData.DataRows.map((r: { slice: (arg0: number, arg1: number) => { forEach: (arg0: (d: any, i: string | number) => any) => void; }; }) => {
      const row = {};
      r.slice(0, 9).forEach((d: any, i: string | number) => (row[this.displayedColumns[i]] = d));
      return row;
    });
displayedColumns: string[] = [];

const displayedColumns = this.viewData.Columns.map((c: { Name: any; }) => c.Name);
    displayedColumns[2] = 'Folder1';
    this.displayedColumns = ['select'].concat(displayedColumns);
    // tslint:disable-next-line: max-line-length
    const fetchedData = this.viewData.DataRows.map((r: { slice: (arg0: number, arg1: number) => { forEach: (arg0: (d: any, i: string | number) => any) => void; }; }) => {
      const row = {};
      r.slice(0, 9).forEach((d: any, i: string | number) => (row[this.displayedColumns[i]] = d));
      return row;
    });

displayedColumns
替换为包含除所选列的id之外的所有列id的列表

displayedColumns: string[] = [];

const displayedColumns = this.viewData.Columns.map((c: { Name: any; }) => c.Name);
    displayedColumns[2] = 'Folder1';
    this.displayedColumns = displayedColumns;
    // tslint:disable-next-line: max-line-length
    const fetchedData = this.viewData.DataRows.map((r: { slice: (arg0: number, arg1: number) => { forEach: (arg0: (d: any, i: string | number) => any) => void; }; }) => {
      const row = {};
      r.slice(0, 9).forEach((d: any, i: string | number) => (row[this.displayedColumns[i]] = d));
      return row;
    });
displayedColumns: string[] = [];

const displayedColumns = this.viewData.Columns.map((c: { Name: any; }) => c.Name);
    displayedColumns[2] = 'Folder1';
    this.displayedColumns = ['select'].concat(displayedColumns);
    // tslint:disable-next-line: max-line-length
    const fetchedData = this.viewData.DataRows.map((r: { slice: (arg0: number, arg1: number) => { forEach: (arg0: (d: any, i: string | number) => any) => void; }; }) => {
      const row = {};
      r.slice(0, 9).forEach((d: any, i: string | number) => (row[this.displayedColumns[i]] = d));
      return row;
    });

最后使用列id列表,其中包含您的数据列id以及选择列的id

看看这里,我为一个和多个select列添加了示例。
(注意:我没有调整multi-select列示例的选择逻辑。)

出现错误是因为您在
显示的列上循环了两次

要修复错误,您需要:

  • 修正“选择”列的定义
  • 从显示的列中排除您的select列id,以防止多次使用它
  • 在行定义的id列表中包括select列id
选择列


如果只想显示一个select列,并且每行都有一个复选框,则需要在此处删除
*ngFor=“…”
。 如果需要多个select列(例如,每个数据列一个),则需要为这些列定义一个唯一ID列表并在其上循环:


其他列

displayedColumns: string[] = [];

const displayedColumns = this.viewData.Columns.map((c: { Name: any; }) => c.Name);
    displayedColumns[2] = 'Folder1';
    this.displayedColumns = displayedColumns;
    // tslint:disable-next-line: max-line-length
    const fetchedData = this.viewData.DataRows.map((r: { slice: (arg0: number, arg1: number) => { forEach: (arg0: (d: any, i: string | number) => any) => void; }; }) => {
      const row = {};
      r.slice(0, 9).forEach((d: any, i: string | number) => (row[this.displayedColumns[i]] = d));
      return row;
    });
displayedColumns: string[] = [];

const displayedColumns = this.viewData.Columns.map((c: { Name: any; }) => c.Name);
    displayedColumns[2] = 'Folder1';
    this.displayedColumns = ['select'].concat(displayedColumns);
    // tslint:disable-next-line: max-line-length
    const fetchedData = this.viewData.DataRows.map((r: { slice: (arg0: number, arg1: number) => { forEach: (arg0: (d: any, i: string | number) => any) => void; }; }) => {
      const row = {};
      r.slice(0, 9).forEach((d: any, i: string | number) => (row[this.displayedColumns[i]] = d));
      return row;
    });

displayedColumns
替换为包含除所选列的id之外的所有列id的列表

displayedColumns: string[] = [];

const displayedColumns = this.viewData.Columns.map((c: { Name: any; }) => c.Name);
    displayedColumns[2] = 'Folder1';
    this.displayedColumns = displayedColumns;
    // tslint:disable-next-line: max-line-length
    const fetchedData = this.viewData.DataRows.map((r: { slice: (arg0: number, arg1: number) => { forEach: (arg0: (d: any, i: string | number) => any) => void; }; }) => {
      const row = {};
      r.slice(0, 9).forEach((d: any, i: string | number) => (row[this.displayedColumns[i]] = d));
      return row;
    });
displayedColumns: string[] = [];

const displayedColumns = this.viewData.Columns.map((c: { Name: any; }) => c.Name);
    displayedColumns[2] = 'Folder1';
    this.displayedColumns = ['select'].concat(displayedColumns);
    // tslint:disable-next-line: max-line-length
    const fetchedData = this.viewData.DataRows.map((r: { slice: (arg0: number, arg1: number) => { forEach: (arg0: (d: any, i: string | number) => any) => void; }; }) => {
      const row = {};
      r.slice(0, 9).forEach((d: any, i: string | number) => (row[this.displayedColumns[i]] = d));
      return row;
    });

最后使用列id列表,其中包含您的数据列id以及选择列的id

看看这里,我为一个和多个select列添加了示例。
(注意:我没有调整multi-select列示例的选择逻辑。)

我认为您的问题是您在
displayedColumns
中多次使用
matColumnDef
首先:

...
    <ng-container matColumnDef="column" *ngFor="let column of displayedColumns">
      <th mat-header-cell *matHeaderCellDef>
        <mat-checkbox (change)="$event ? masterToggle() : null"
                      [checked]="selection.hasValue() && isAllSelected()"
                      [indeterminate]="selection.hasValue() && !isAllSelected()">
        </mat-checkbox>
...
2) 第一列(复选框)应为
select
,不应包含在其他列的
*ngFor
中:

view.component.html

<mat-card-content>
<div class="view-container mat-elevation-z8">
  <table mat-table [dataSource]="dataSource" matSort>

    <ng-container matColumnDef="column" *ngFor="let column of displayedColumns">
      <th mat-header-cell *matHeaderCellDef>
        <mat-checkbox (change)="$event ? masterToggle() : null"
                      [checked]="selection.hasValue() && isAllSelected()"
                      [indeterminate]="selection.hasValue() && !isAllSelected()">
        </mat-checkbox>
      </th>
      <td mat-cell *matCellDef="let action">
        <mat-checkbox (click)="$event.stopPropagation()"
                      (change)="$event ? selection.toggle(row) : null"
                      [checked]="selection.isSelected(row)">
        </mat-checkbox>
      </td>
    </ng-container>

    <ng-container [matColumnDef]="column" *ngFor="let column of displayedColumns">
      <th mat-header-cell *matHeaderCellDef mat-sort-header>
        {{ column }}
        <mat-icon aria-hidden="false" aria-label="filter icon">more_horiz</mat-icon>
      </th>
      <td mat-cell *matCellDef="let action">{{ action[column] }}
      </td>
    </ng-container>

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

  <mat-paginator [pageSizeOptions]="pageSizeOptions" showFirstLastButtons></mat-paginator>
</div>
<mat-card-content>
<div class="view-container mat-elevation-z8">
  <table mat-table [dataSource]="dataSource" matSort>

    <ng-container matColumnDef="select">
      <th mat-header-cell *matHeaderCellDef>
        <mat-checkbox (change)="$event ? masterToggle() : null"
                      [checked]="selection.hasValue() && isAllSelected()"
                      [indeterminate]="selection.hasValue() && !isAllSelected()">
        </mat-checkbox>
      </th>
      <td mat-cell *matCellDef="let row">
        <mat-checkbox (click)="$event.stopPropagation()"
                      (change)="$event ? selection.toggle(row) : null"
                      [checked]="selection.isSelected(row)">
        </mat-checkbox>
      </td>
    </ng-container>

    <ng-container [matColumnDef]="column" *ngFor="let column of displayedColumns | slice:1 ">
      <th mat-header-cell *matHeaderCellDef mat-sort-header>
        {{ column }}
        <mat-icon aria-hidden="false" aria-label="filter icon">more_horiz</mat-icon>
      </th>
      <td mat-cell *matCellDef="let action">{{ action[column] }}
      </td>
    </ng-container>

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

  <mat-paginator [pageSizeOptions]="pageSizeOptions" showFirstLastButtons></mat-paginator>
</div>

{{column}}
更多霍里兹
{{操作[列]}

现在,它应该像预期的那样工作

我认为您的问题是您在
displayedColumns
中多次使用
matColumnDef
首先:

...
    <ng-container matColumnDef="column" *ngFor="let column of displayedColumns">
      <th mat-header-cell *matHeaderCellDef>
        <mat-checkbox (change)="$event ? masterToggle() : null"
                      [checked]="selection.hasValue() && isAllSelected()"
                      [indeterminate]="selection.hasValue() && !isAllSelected()">
        </mat-checkbox>
...
2) 第一列(复选框)应为
select
,不应包含在其他列的
*ngFor
中:

view.component.html

<mat-card-content>
<div class="view-container mat-elevation-z8">
  <table mat-table [dataSource]="dataSource" matSort>

    <ng-container matColumnDef="column" *ngFor="let column of displayedColumns">
      <th mat-header-cell *matHeaderCellDef>
        <mat-checkbox (change)="$event ? masterToggle() : null"
                      [checked]="selection.hasValue() && isAllSelected()"
                      [indeterminate]="selection.hasValue() && !isAllSelected()">
        </mat-checkbox>
      </th>
      <td mat-cell *matCellDef="let action">
        <mat-checkbox (click)="$event.stopPropagation()"
                      (change)="$event ? selection.toggle(row) : null"
                      [checked]="selection.isSelected(row)">
        </mat-checkbox>
      </td>
    </ng-container>

    <ng-container [matColumnDef]="column" *ngFor="let column of displayedColumns">
      <th mat-header-cell *matHeaderCellDef mat-sort-header>
        {{ column }}
        <mat-icon aria-hidden="false" aria-label="filter icon">more_horiz</mat-icon>
      </th>
      <td mat-cell *matCellDef="let action">{{ action[column] }}
      </td>
    </ng-container>

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

  <mat-paginator [pageSizeOptions]="pageSizeOptions" showFirstLastButtons></mat-paginator>
</div>
<mat-card-content>
<div class="view-container mat-elevation-z8">
  <table mat-table [dataSource]="dataSource" matSort>

    <ng-container matColumnDef="select">
      <th mat-header-cell *matHeaderCellDef>
        <mat-checkbox (change)="$event ? masterToggle() : null"
                      [checked]="selection.hasValue() && isAllSelected()"
                      [indeterminate]="selection.hasValue() && !isAllSelected()">
        </mat-checkbox>
      </th>
      <td mat-cell *matCellDef="let row">
        <mat-checkbox (click)="$event.stopPropagation()"
                      (change)="$event ? selection.toggle(row) : null"
                      [checked]="selection.isSelected(row)">
        </mat-checkbox>
      </td>
    </ng-container>

    <ng-container [matColumnDef]="column" *ngFor="let column of displayedColumns | slice:1 ">
      <th mat-header-cell *matHeaderCellDef mat-sort-header>
        {{ column }}
        <mat-icon aria-hidden="false" aria-label="filter icon">more_horiz</mat-icon>
      </th>
      <td mat-cell *matCellDef="let action">{{ action[column] }}
      </td>
    </ng-container>

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

  <mat-paginator [pageSizeOptions]="pageSizeOptions" showFirstLastButtons></mat-paginator>
</div>

{{column}}
更多霍里兹
{{操作[列]}

现在,它应该像预期的那样工作

你得给我们看看你的专栏。你能发布显示的栏目吗?这就是重复的地方。确保集合包含唯一的值。已发布的displayedColumns..“displayedColumns”中必须包含重复的值。你能试试这个记录内容吗?log(JSON.stringify(displayedColumns | |[]));我得到了一个“错误错误:提供了重复的列定义名称:”column“。错误,但我相信这与HTMLNG容器有关。我想做的是为一行添加一个复选框你需要为每一列设置复选框还是每一行仅设置一个复选框?你必须向我们显示你的列。你能发布显示的栏目吗?这就是重复的地方。确保集合包含唯一的值。已发布的displayedColumns..“displayedColumns”中必须包含重复的值。你能试试这个记录内容吗?log(JSON.stringify(displayedColumns | |[]));我得到了一个“错误错误:提供了重复的列定义名称:”column“。错误,但我相信这与HTMLNG容器有关。我想做的是为一行添加一个复选框您需要为每一列设置复选框还是每一行仅设置一个复选框?我还没有测试您的解决方案,但只有在显示列的顺序不变的情况下,使用静态值对显示列进行切片才能起作用。对于更通用的方法,最好将静态列和动态列分开。你是对的。但是,为了防止您提到的问题,这就是我这样做的原因:
view.component.ts
中的
['select'].concat(displayedColumns)
,因此您要确保第一个元素(索引0)始终是
select
列。我还没有测试您的解决方案,但是,只有在显示列的顺序不变的情况下,使用静态值对显示列进行切片才会起作用。对于更通用的方法,最好将静态