javascript - 如何使用 Angular Material 在具有可扩展行的表中创建嵌套垫表

标签 javascript html angular typescript angular-material

我有以下数据

[
    {
        "_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"然后它没有 child 。我试图创建一个动态表,但我被困在如何使用嵌套表使其可折叠/可扩展。
这是我在 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);
}

所需格式 :-->
nested table

嵌套格式如下

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



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

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

最佳答案

Note: For those who want to skip the lengthy explanation, here is the StackBlitz example.



你真正想要的是创建一个嵌套的 mat-table其中所有嵌套表都是可排序的,也可以过滤。

首先,由于您需要在嵌套表中使用过滤和排序,您需要创建一个新的MatTableDataSource为了它。这可以在您创建主 dataSource 时完成。在 ngOnInit如下所示。

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);

从可扩展行 example in the docs ,我们可以看到如何创建一个可扩展的行。在可扩展行中,我们现在将有一个表格以及 Filter输入。我们将添加一些条件,以便该行仅在存在 addresses 时才可扩展。当下。

<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 的用户消除悬停。

这是负责添加 background-color 的 CSS悬停时

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

所以我们只需要添加example-element-row如果该行有 address,则归类到我们的行.如果它没有地址,则该行不应该是可点击的,并且不应该有一个悬停来向用户表明该行实际上是不可点击的。

<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当用户单击此函数中的行时。

@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函数,以便可以过滤嵌套表。

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

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

这是 StackBlitz 上的一个工作示例.

关于javascript - 如何使用 Angular Material 在具有可扩展行的表中创建嵌套垫表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57810336/

相关文章:

javascript - 对于谷歌地图标记,是否可以在 svg 中包含多种颜色

javascript - ionic 固定内容在底部

javascript - 如何在打印时隐藏打印按钮?

css - Bootstrap 4 - 带选项卡的模态标题 - 如何降低标题高度

angular - 由于添加了新成员,如何更新 Angular 的 html 部分中的 ngFor ?

javascript - Polymer:按下纸张按钮后获取纸张对话框内的纸张输入值 "ok"

javascript - 为什么我的 iframe 不调整大小以适合其内容?

javascript - 带有固定顶部菜单的翻转菜单

angular - 具有静态数据的 Material Design 数据表布局

javascript - Cypress Angular 何时可以开始测试?