【问题标题】:Angular 6 - Looping through Material Table inside Material Expansion PanelAngular 6 - 循环通过材料扩展面板内的材料表
【发布时间】:2018-09-27 19:57:41
【问题描述】:

我有一个问题,我有点不知所措。我有材料扩展面板,通过循环包含我拥有的数据的变量来填充标题,这是一个对象数组 - 在该对象数组中,有一个键,其值是扩展面板标题。还有一个键,它的值是另一个对象数组,我想循环遍历它以填充每个扩展面板内的材质表。

这是我目前所拥有的......

titleGroups.ts:

export const titles = [
    {
        title: 'First Title',
        titleId: 'firstTitle',
        info: [
            { name: 'Info One', code: 'infoOne' },
            { name: 'Info Two', code: 'infoTwo' },
            { name: 'Info Three', code: 'infoThree' },
            { name: 'Info Four', code: 'infoFour' }
        ]
    },
    {
        title: 'Second Title',
        titleId: 'secondTitle',
        info: [
            { name: 'Package', code: 'package' },
            { name: 'Package Two', code: 'packageTwo' } 
        ]
    },
    {
        title: 'Third Title',
        titleId: 'thirdTitle',
        info: [
            { name: 'Widget One', code: 'widgetOne' },
            { name: 'Widget Two', code: 'widgetTwo' },
            { name: 'Widget Three', code: 'widgetThree' },
            { name: 'Widget Four', code: 'widgetFour' }
        ]
    }
]

title.component.ts:

import {Component} from '@angular/core';
import {SelectionModel} from '@angular/cdk/collections';
import {MatTableDataSource} from '@angular/material';
import {titles} from './titleGroups';

export interface TitleNames {
    name: string;
}

const TITLES: any[] = titles;

let TITLE_NAMES;
for(let i = 0; i < TITLES.length; i++)
    for(let j = 0; j < TITLES[i].info.length; j++)
        TITLE_NAMES = TITLES[i].info;

@Component({
    selector: 'aa-titles',
    templateUrl: './aa-titles.component.html',
    styleUrls: ['./aa-titles.component.scss']
})

export class TitlesComponent {
    displayedColumns: string[] = ['select', 'name'];
    dataSource = new MatTableDataSource<TitleNames>(TITLE_NAMES);
    selection = new SelectionModel<TitleNames>(true, []);
    titleData: any;

    constructor() {
        this.titleData = TITLES;
    }

    isAllSelected() {
        const numSelected = this.selection.selected.length;
        const numRows = this.dataSource.data.length;

        return numSelected === numRows;
    }

    masterToggle() {
        this.isAllSelected() ?
            this.selection.clear() :
            this.dataSource.data.forEach(row => this.selection.select(row));
    }
}

title.component.html:

<mat-accordion multi="true">
    <mat-expansion-panel *ngFor="let item of titleData">
        <mat-expansion-panel-header>{{item.title}}</mat-expansion-panel-header>

        <table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
            <!-- Checkbox Column -->
            <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>

            <!-- Name Column -->
            <ng-container matColumnDef="name">
                <th mat-header-cell *matHeaderCellDef> Name </th>
                <td mat-cell *matCellDef="let element"> {{element.name}} </td>
            </ng-container>

            <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
            <tr mat-row *matRowDef="let row; columns: displayedColumns;"
                (click)="selection.toggle(row)">
            </tr>
        </table>
    </mat-expansion-panel>
</mat-accordion>

发生的情况是,在每个展开面板下,它仅显示每个展开面板下 titleGroups.ts 中标题的最后一个元素的数据。

我想要的是让相应的扩展面板显示正确的数据

显示表格的第一个标题扩展面板:

Info One

Info Two

Info Three

Info Four

第二个标题扩展面板显示一个表格:

Package

Package Two

等等。我不知道如何做到这一点 - 任何帮助将不胜感激,谢谢!

【问题讨论】:

    标签: javascript angular angular-material angular-material-6


    【解决方案1】:

    您应该为每个表定义分开的dataSource-s 和selectionModel-s: 例如,您可以在constructor 中定义这样的数组:

    this.titlesForIterate = titles.map(item => { 
        // I'm not doing it here, but you can also deep clone the item object first 
        item.dataSource = new MatTableDataSource<WidgetNames>(item.info);
        item.selectionModel = new SelectionModel<TitleNames>(true, []);
        return item;
    };
    

    然后在expansionPanels的*ngFor中使用titlesForIterate。

    <mat-expansion-panel *ngFor="let item of titlesForIterate">
    

    然后在每个扩展面板中使用他们自己的dataSource 和selectionModel 成员作为他们的表。

    <table mat-table [dataSource]="item.dataSource" class="mat-elevation-z8">
    
        ...
                    <mat-checkbox (change)="$event ? masterToggle() : null"
                                  [checked]="item.selection.hasValue() && isAllSelected(item)"
                                  [indeterminate]="item.selection.hasValue() && !isAllSelected(item)">
                    </mat-checkbox>
        ...
    

    注意:不要忘记重构isAllSelected 方法以接收父对象作为参数。

    【讨论】:

    • 谢谢你的回答,但我很难处理第一部分——this.titlesForIterate——我是否在构造函数中定义它?我是否需要先定义titlesForIterate才能使用this.titlesForIterate?抱歉,我对 Angular 6 很陌生,但我仍然对所有事情都束手无策。我理解你的大部分答案,但试图分解如何逐步到达那里......
    • 是的,您应该在构造函数中定义titlesForIterate(并在类中声明它)。我已经更新了我的答案/w it。
    猜你喜欢
    • 2018-03-23
    • 1970-01-01
    • 1970-01-01
    • 2017-11-18
    • 2018-06-26
    • 2020-04-19
    • 2022-01-22
    • 1970-01-01
    • 2020-09-06
    相关资源
    最近更新 更多