簡體   English   中英

如何使用角材料在具有可擴展行的表格中創建嵌套墊表

[英]How to create a nested mat-table in a table with expandable rows using 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"那么它沒有孩子。 我試圖創建一個動態表,但我被困在如何使用嵌套表使其可折疊/可擴展。 這是我在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

當我們單擊該特定行時,它必須展開並在帶有列名和行數據的表中顯示嵌套數據。

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

注意:對於那些想跳過冗長解釋的人,這里是StackBlitz 示例

您真正想要的是創建一個嵌套的mat-table ,其中所有嵌套的表都是可排序的,也可以過濾。

首先,由於您需要在嵌套表中使用過濾和排序,您需要為其創建一個新的MatTableDataSource 這可以在您在ngOnInit創建主dataSource時最初完成,如下所示。

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該行才可擴展。

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

因此,如果行有一個address我們只需要將example-element-row類添加到我們的行中。 如果它沒有地址,則該行不應該是可點擊的,並且不應該有一個懸停來向用戶表明該行實際上是不可點擊的。

<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上的一個工作示例。

查看文檔中的示例,尤其是帶有可擴展行示例

  • 您在<mat-table>中缺少multiTemplateDataRows指令
  • 缺少@detailExpand觸發器
  • ...

是文檔中包含您的數據的示例

編輯(關於評論)

以下是獲取動態列的方法:

將此添加到您的組件中

  getKeys(object): string[] {
    return Object.keys(object);
  }

使用模板中的方法(根據附加的詳細信息屏幕和nested鍵下的多個元素的注釋更新模板):

<div class="example-element-descriptions">
    <div *ngFor="let nested of element['nested']"
         class="example-element-description">
        <div *ngIf="element['info.dependent'] === 'parent'">
            <div class="example-element-description__header">
                <div class="example-element-description__cell"
                     *ngFor="let key of getKeys(nested)">{{key}}</div>
            </div>
            <div class="example-element-description__content">
                <div class="example-element-description__cell"
                     *ngFor="let key of getKeys(nested)">{{element[key]}}
                </div>
            </div>
        </div>
        <div *ngIf="element['info.dependent'] === 'no_parent'">no parent</div>
    </div>
</div>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM