如何使用角形材料在具有可扩展行的表中创建嵌套的席子表 [英] How to create a nested mat-table in a table with expandable rows using angular material

查看:103
本文介绍了如何使用角形材料在具有可扩展行的表中创建嵌套的席子表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下数据

[
    {
        "_id": "c9d5ab1a",
        "subdomain": "wing",
        "domain": "aircraft",
        "part_id": "c9d5ab1a",
        "info.mimetype": "application/json",
        "info.dependent": "parent",
        "nested": [
            {
                "domain": "aircraft",
                "_id": "c1859902",
                "info.mimetype": "image/jpeg",
                "info.dependent": "c9d5ab1a",
                "part_id": "c1859902",
                "subdomain": "tail"
            }
        ]
    },
    {
        "_id": "1b0b0a26",
        "subdomain": "fuel",
        "domain": "aircraft",
        "part_id": "1b0b0a26",
        "info.mimetype": "image/jpeg",
        "info.dependent": "no_parent"
    }
]

如果"info.dependent": "parent"则嵌套,如果"info.dependent": "no_parent"则没有子.我试图创建一个动态表,但是我仍然坚持如何使它与嵌套表可折叠/可扩展. 这是我在 stackblitz 上的代码.

Here if "info.dependent": "parent" then it is nested and if "info.dependent": "no_parent" then it does not have a child. I tried to create a dynamic table but I am stuck on how to make it collapsible/expandable with a nested table. Here is my code on stackblitz.

<mat-table class=" mat-elevation-z8" [dataSource]="dataSource">

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

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

</mat-table>

.ts

public data = [
    {
        "_id": "c9d5ab1a",
        "subdomain": "wing",
        "domain": "aircraft",
        "part_id": "c9d5ab1a",
        "info.mimetype": "application/json",
        "info.dependent": "parent",
        "nested": [
            {
                "domain": "aircraft",
                "_id": "c1859902",
                "info.mimetype": "image/jpeg",
                "info.dependent": "c9d5ab1a",
                "part_id": "c1859902",
                "subdomain": "tail"
            }
        ]
    },
    {
        "_id": "1b0b0a26",
        "subdomain": "fuel",
        "domain": "aircraft",
        "part_id": "1b0b0a26",
        "info.mimetype": "image/jpeg",
        "info.dependent": "no_parent"
    }
];

dataSource = new MatTableDataSource([]);
displayedColumns = ['_id', 'subdomain', 'domain', 'part_id', 'info.mimetype', 'info.dependent'];

constructor(){
    this.displayedColumns = this.displayedColumns;
    this.dataSource = new MatTableDataSource(this.data);
}

所需格式:->

嵌套格式如下

第1行-> _id,subdomain,domain,info.dependent

row 1 --> _id ,subdomain,domain,info.dependent

当我们单击该特定行时,它必须展开并在具有列名和行数据的表中显示嵌套数据.

When we click on that particular row, then it has to expand and display the nested data in a table with the column names and row data.

"nested": [
    {
        "domain": "aircraft",
        "_id": "c1859902",
        "info.mimetype": "image/jpeg",
        "info.dependent": "c9d5ab1a",
        "part_id": "c1859902",
        "subdomain": "tail"
    }
]

推荐答案

注意:对于那些想跳过冗长解释的人,这是 StackBlitz示例.

您真正想要的是创建一个嵌套的mat-table,其中所有嵌套表都是可排序的,并且也可以通过它进行过滤.

What you actually want is to create a nested mat-table where all the nested tables are sortable and can be filtered through as well.

首先,由于需要在嵌套表中使用过滤和排序,因此需要为其创建一个新的MatTableDataSource.最初可以在如下所示的ngOnInit中创建主dataSource时完成.

Firstly, since you need to use filtering and sorting in your nested table, you need to create a new MatTableDataSource for it. This can be done initially when you create the main dataSource in the ngOnInit like below.

usersData: User[] = [];

USERS.forEach(user => {
    if (user.addresses && Array.isArray(user.addresses) && user.addresses.length) {
        this.usersData = [...this.usersData, { ...user, addresses: new MatTableDataSource(user.addresses) }];
    } else {
        this.usersData = [...this.usersData, user];
    }
});
this.dataSource = new MatTableDataSource(this.usersData);

在文档中的可扩展行示例中,我们可以看到如何创建可扩展行.在可扩展行中,我们现在将有一个表以及Filter输入.我们将添加一些条件,以使该行仅在存在addresses的情况下才可扩展.

From the expandable rows example in the docs, we can see how to create an expandable row. In the expandable row, we will now have a table along with the Filter input. We will add some conditions so that the row is expandable only if there are addresses present.

<div class="example-element-detail" *ngIf="element.addresses?.data.length"
    [@detailExpand]="element == expandedElement ? 'expanded' : 'collapsed'">
    <div class="inner-table mat-elevation-z8" *ngIf="expandedElement">
        <mat-form-field>
            <input matInput (keyup)="applyFilter($event.target.value)" placeholder="Filter">
        </mat-form-field>
        <table #innerTables mat-table #innerSort="matSort" [dataSource]="element.addresses" matSort>
            <ng-container matColumnDef="{{innerColumn}}" *ngFor="let innerColumn of innerDisplayedColumns">
                <th mat-header-cell *matHeaderCellDef mat-sort-header> {{innerColumn}} </th>
                <td mat-cell *matCellDef="let element"> {{element[innerColumn]}} </td>
            </ng-container>
            <tr mat-header-row *matHeaderRowDef="innerDisplayedColumns"></tr>
            <tr mat-row *matRowDef="let row; columns: innerDisplayedColumns;"></tr>
        </table>
    </div>
</div>

现在,仅当存在嵌套元素时,行才会展开,我们需要为没有addresses

Now that the row expands only if there are nested elements, we need to get rid of the hover for the users which have no addresses

这里是CSS,负责在悬停时添加background-color

Here is the CSS responsible for adding a background-color on hover

tr.example-element-row:not(.example-expanded-row):hover {
    background: #777;
}

因此,如果该行具有address,则只需向该行添加example-element-row类.如果没有地址,则该行不应是可单击的,并且不应有悬停指示用户该行实际上是不可单击的.

So we just need to add the example-element-row class to our row if the row has an address. If it has no address, the row should not be clickable and there should not be a hover which indicates to the user that the row is in fact not clickable.

<tr mat-row *matRowDef="let element; columns: columnsToDisplay;" 
    [class.example-element-row]="element.addresses?.data.length"
    [class.example-expanded-row]="expandedElement === element"
    (click)="toggleRow(element)">
</tr>

toggleRow中,我们将定义单击模板中的一行时发生的逻辑.当用户单击此功能中的行时,我们还将实现sort.

In toggleRow, we will define the logic for what happens when you click a row in the template. We will also implement sort when the user clicks on the row in this function.

@ViewChildren('innerSort') innerSort: QueryList<MatSort>;

toggleRow(element: User) {
    element.addresses && (element.addresses as MatTableDataSource<Address>).data.length ? (this.expandedElement = this.expandedElement === element ? null : element) : null;
    this.cd.detectChanges();
    this.innerTables.forEach((table, index) => (table.dataSource as MatTableDataSource<Address>).sort = this.innerSort.toArray()[index]);
}

最后,我们需要定义applyFilter函数,以便可以过滤嵌套表.

Finally, we need to define the applyFilter function so the nested tables can be filtered.

@ViewChildren('innerTables') innerTables: QueryList<MatTable<Address>>;

applyFilter(filterValue: string) {
    this.innerTables.forEach((table, index) => (table.dataSource as MatTableDataSource<Address>).filter = filterValue.trim().toLowerCase());
}

这是 StackBlitz 上的有效示例.

这篇关于如何使用角形材料在具有可扩展行的表中创建嵌套的席子表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆