使用带有展开/折叠行的 mat-table 数据显示树状结构

问题描述 投票:0回答:1

Angular 新手,希望有人可以帮助我。我需要显示 mat-table,其中可能有多行数据可以展开/折叠。这是我想要显示的结构:

export interface Entity {
  name: string;
  age: number;
  children?: Entity[];
}

const Entities: Entity[] = [
  {
    name: 'P1',
    age: 40,
    children: [
      {
        name: 'C1a',
        age: 18
      },
      {
        name: 'C1b',
        protocol: 15      }
    ]
  },
  {
    name: 'P2',
    age: 43,
    children: [
      {
        name: 'C2a',
        age: 21,
      },
      {
        name: 'C2b',
        age: 22
      }
    ]
  }
]

在上面,我想显示这样的行:

姓名年龄
P1 40
  C1a 18
  C1b 15
P2 43
  C2a 21
  C2b 22

单击 P1/P2 时,行应展开/折叠。此外,所有列都应该对齐。我发现的几乎所有示例都使用外表和内表,但这意味着列没有对齐。有没有办法对所有内容使用单个表或以某种方式对齐列中的数据?

angular angular-material
1个回答
0
投票

我们可以使用

MatTreeFlatDataSource
来达到这个目的,只需添加一个嵌套结构作为数据源就可以了!

完整代码:

TS:

import { FlatTreeControl } from '@angular/cdk/tree';
import { Component } from '@angular/core';
import {
  MatTreeFlatDataSource,
  MatTreeFlattener,
} from '@angular/material/tree';

export interface Entity {
  name: string;
  age: number;
  children?: Entity[];
}

const TREE_DATA: Entity[] = [
  {
    name: 'P1',
    age: 40,
    children: [
      {
        name: 'C1a',
        age: 18,
      },
      {
        name: 'C1b',
        age: 15,
      },
    ],
  },
  {
    name: 'P2',
    age: 43,
    children: [
      {
        name: 'C2a',
        age: 21,
      },
      {
        name: 'C2b',
        age: 22,
      },
    ],
  },
];

interface ExampleFlatNode {
  expandable: boolean;
  name: string;
  age: number;
  level: number;
}

/**
 * @title Basic use of `<table mat-table>`
 */
@Component({
  selector: 'table-basic-example',
  styleUrls: ['table-basic-example.css'],
  templateUrl: 'table-basic-example.html',
})
export class TableBasicExample {
  displayedColumns: string[] = ['name', 'age'];

  private transformer = (node: Entity, level: number) => {
    return {
      expandable: !!node.children && node.children.length > 0,
      name: node.name,
      age: node.age,
      level: level,
    };
  };

  treeControl = new FlatTreeControl<ExampleFlatNode>(
    (node) => node.level,
    (node) => node.expandable
  );

  treeFlattener = new MatTreeFlattener(
    this.transformer,
    (node) => node.level,
    (node) => node.expandable,
    (node) => node.children
  );

  dataSource = new MatTreeFlatDataSource(this.treeControl, this.treeFlattener);

  constructor() {
    this.dataSource.data = TREE_DATA;
  }

  hasChild = (_: number, node: ExampleFlatNode) => node.expandable;
}

HTML:

<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
  <ng-container matColumnDef="name">
    <th mat-header-cell *matHeaderCellDef>
      <span [style.paddingLeft.px]="40"> Name </span>
    </th>
    <td mat-cell *matCellDef="let data">
      <button
        mat-icon-button
        [style.visibility]="!data.expandable ? 'hidden' : ''"
        [style.marginLeft.px]="data.level * 32"
        (click)="treeControl.toggle(data)"
      >
        <mat-icon class="mat-icon-rtl-mirror">
          {{treeControl.isExpanded(data) ? 'expand_more' : 'chevron_right'}}
        </mat-icon>
      </button>

      {{data.name}}
    </td>
  </ng-container>

  <ng-container matColumnDef="age">
    <th mat-header-cell *matHeaderCellDef>Age</th>
    <td mat-cell *matCellDef="let data">{{data.age}}</td>
  </ng-container>

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

Stackblitz 演示

© www.soinside.com 2019 - 2024. All rights reserved.