【问题标题】:How to add multiple tables each having filter, sort, pagination in Angular material?如何在Angular材料中添加多个表,每个表都具有过滤器、排序、分页?
【发布时间】:2020-06-23 17:20:45
【问题描述】:

我环顾四周,没有找到支持 n 在一页中的表格数量的答案,其中每个表格都有自己的过滤器、排序和分页。

在https://material.angular.io/ 上,他们给出了一个表格一个页面的示例。

这是我为一张桌子写的-

HTML

<mat-form-field>
    <mat-label>Filter</mat-label>
    <input matInput (keyup)="applyFilter($event)" placeholder="Ex. Mia">
</mat-form-field>

<table mat-table [dataSource]="dataSource" multiTemplateDataRows matSort>

    <ng-container matColumnDef="{{column}}" *ngFor="let column of columnsToDisplay">
        <th mat-header-cell *matHeaderCellDef mat-sort-header> {{column}} </th>
        <td mat-cell *matCellDef="let element"> {{element[column]}} </td>
    </ng-container>

    <ng-container matColumnDef="expandedDetail">
        <td mat-cell *matCellDef="let element" [attr.colspan]="columnsToDisplay.length">
            <div class="table-element-detail" [@detailExpand]="element == expandedElement ? 'expanded' : 'collapsed'">
                <div class="table-element-diagram">
                    <div class="table-element-position"> {{element.position}} </div>
                    <div class="table-element-symbol"> {{element.symbol}} </div>
                    <div class="table-element-name"> {{element.name}} </div>
                    <div class="table-element-weight"> {{element.weight}} </div>
                </div>
                <div class="table-element-description">
                    {{element.description}}
                    <span class="table-element-description-attribution"> -- Wikipedia </span>
                </div>
            </div>
        </td>
    </ng-container>

    <tr mat-header-row *matHeaderRowDef="columnsToDisplay"></tr>
    <tr mat-row *matRowDef="let element; columns: columnsToDisplay;" class="table-element-row"
        [class.table-expanded-row]="expandedElement === element"
        (click)="expandedElement = expandedElement === element ? null : element">
    </tr>
    <tr mat-row *matRowDef="let row; columns: ['expandedDetail']" class="table-detail-row"></tr>

</table>

<mat-paginator [pageSizeOptions]="[5, 10, 25, 100]"></mat-paginator>

TS

import { Component, ViewChild, OnInit, AfterViewInit } from '@angular/core';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table';
import { animate, state, style, transition, trigger } from '@angular/animations';

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css'],
    animations: [
        trigger('detailExpand', [
            state('collapsed', style({ height: '0px', minHeight: '0' })),
            state('expanded', style({ height: '*' })),
            transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)')),
        ]),
    ]
})
export class AppComponent implements OnInit, AfterViewInit {

    @ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
    @ViewChild(MatSort, { static: true }) sort: MatSort;

    columnsToDisplay = ['name', 'weight', 'symbol', 'position'];
    expandedElement: PeriodicElement | null;
    dataSource: MatTableDataSource<PeriodicElement>;

    constructor() { }

    ngOnInit() {
        this.dataSource = new MatTableDataSource(ELEMENT_DATA);
    }

    ngAfterViewInit(): void {
        this.dataSource.paginator = this.paginator;
        this.dataSource.sort = this.sort;
    }

    applyFilter(event: Event) {
        const filterValue = (event.target as HTMLInputElement).value;
        this.dataSource.filter = filterValue.trim().toLowerCase();
        if (this.dataSource.paginator) {
            this.dataSource.paginator.firstPage();
        }
    }
}

export interface PeriodicElement {
    name: string;
    position: number;
    weight: number;
    symbol: string;
    description: string;
}

const ELEMENT_DATA: PeriodicElement[] = [
    {
        position: 1,
        name: 'Hydrogen',
        weight: 1.0079,
        symbol: 'H',
        description: `Hydrogen is a chemical element with symbol H and atomic number 1. With a standard
            atomic weight of 1.008, hydrogen is the lightest element on the periodic table.`
    }, {
        position: 2,
        name: 'Helium',
        weight: 4.0026,
        symbol: 'He',
        description: `Helium is a chemical element with symbol He and atomic number 2. It is a
            colorless, odorless, tasteless, non-toxic, inert, monatomic gas, the first in the noble gas
            group in the periodic table. Its boiling point is the lowest among all the elements.`
    }, {
        position: 3,
        name: 'Lithium',
        weight: 6.941,
        symbol: 'Li',
        description: `Lithium is a chemical element with symbol Li and atomic number 3. It is a soft,
            silvery-white alkali metal. Under standard conditions, it is the lightest metal and the
            lightest solid element.`
    }, {
        position: 4,
        name: 'Beryllium',
        weight: 9.0122,
        symbol: 'Be',
        description: `Beryllium is a chemical element with symbol Be and atomic number 4. It is a
            relatively rare element in the universe, usually occurring as a product of the spallation of
            larger atomic nuclei that have collided with cosmic rays.`
    }, {
        position: 5,
        name: 'Boron',
        weight: 10.811,
        symbol: 'B',
        description: `Boron is a chemical element with symbol B and atomic number 5. Produced entirely
            by cosmic ray spallation and supernovae and not by stellar nucleosynthesis, it is a
            low-abundance element in the Solar system and in the Earth's crust.`
    }, {
        position: 6,
        name: 'Carbon',
        weight: 12.0107,
        symbol: 'C',
        description: `Carbon is a chemical element with symbol C and atomic number 6. It is nonmetallic
            and tetravalent—making four electrons available to form covalent chemical bonds. It belongs
            to group 14 of the periodic table.`
    }, {
        position: 7,
        name: 'Nitrogen',
        weight: 14.0067,
        symbol: 'N',
        description: `Nitrogen is a chemical element with symbol N and atomic number 7. It was first
            discovered and isolated by Scottish physician Daniel Rutherford in 1772.`
    }, {
        position: 8,
        name: 'Oxygen',
        weight: 15.9994,
        symbol: 'O',
        description: `Oxygen is a chemical element with symbol O and atomic number 8. It is a member of
            the chalcogen group on the periodic table, a highly reactive nonmetal, and an oxidizing
            agent that readily forms oxides with most elements as well as with other compounds.`
    }, {
        position: 9,
        name: 'Fluorine',
        weight: 18.9984,
        symbol: 'F',
        description: `Fluorine is a chemical element with symbol F and atomic number 9. It is the
            lightest halogen and exists as a highly toxic pale yellow diatomic gas at standard
            conditions.`
    }, {
        position: 10,
        name: 'Neon',
        weight: 20.1797,
        symbol: 'Ne',
        description: `Neon is a chemical element with symbol Ne and atomic number 10. It is a noble gas.
            Neon is a colorless, odorless, inert monatomic gas under standard conditions, with about
            two-thirds the density of air.`
    },
];

CSS

table {
    width: 100%;
}

tr.table-detail-row {
    height: 0;
}

tr.table-element-row:not(.table-expanded-row):hover {
    background: whitesmoke;
}

tr.table-element-row:not(.table-expanded-row):active {
    background: #efefef;
}

.table-element-row td {
    border-bottom-width: 0;
}

.table-element-detail {
    overflow: hidden;
    display: flex;
}

.table-element-diagram {
    min-width: 80px;
    border: 2px solid black;
    padding: 8px;
    font-weight: lighter;
    margin: 8px 0;
    height: 104px;
}

.table-element-symbol {
    font-weight: bold;
    font-size: 40px;
    line-height: normal;
}

.table-element-description {
    padding: 16px;
}

.table-element-description-attribution {
    opacity: 0.5;
}

上面的代码大部分取自https://material.angular.io/,没有问题,效果很好。现在,我正在寻找可以使该表在 *ngFor 中工作的东西,支持过滤、排序和分页。

【问题讨论】:

    标签: angular angular-material


    【解决方案1】:

    您将需要使用@ViewChildren 而不是@ViewChild 并使用QueryList 来有效地阅读儿童。

    组件视图的初始化完成后,您还需要ngAfterViewInit() 来更新分页器和排序。

    请在字里行间阅读 cmets。

    TS

    import { Component, ViewChild, OnInit, AfterViewInit, QueryList, ViewChildren } from '@angular/core';
    import { MatPaginator } from '@angular/material/paginator';
    import { MatSort } from '@angular/material/sort';
    import { MatTableDataSource } from '@angular/material/table';
    import { animate, state, style, transition, trigger } from '@angular/animations';
    
    @Component({
        selector: 'app-root',
        templateUrl: './app.component.html',
        styleUrls: ['./app.component.css'],
        animations: [
            trigger('detailExpand', [
                state('collapsed', style({ height: '0px', minHeight: '0' })),
                state('expanded', style({ height: '*' })),
                transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)')),
            ]),
        ]
    })
    export class AppComponent implements OnInit, AfterViewInit {
    
        // @ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
        // @ViewChild(MatSort, { static: true }) sort: MatSort;
    
        // using ViewChildren and QueryList
        @ViewChildren(MatPaginator) paginator = new QueryList<MatPaginator>();
        @ViewChildren(MatSort) sort = new QueryList<MatSort>();
    
        // columnsToDisplay = ['name', 'weight', 'symbol', 'position'];
        // expandedElement: PeriodicElement | null;
        // dataSource: MatTableDataSource<PeriodicElement>;
    
        // our loop runs on this
        tables: any = [];
    
        constructor() { }
    
        ngOnInit() {
            // filling in each table data for table 1, 2, and 3
            // use it however you'd like to
            [1, 2, 3].forEach(tableNumber => {
                this.tables.push({
                    columnsToDisplay: ['name', 'weight', 'symbol', 'position'],
                    expandedElement: null,
                    dataSource: new MatTableDataSource(ELEMENT_DATA),
                    paginator: null,
                    sort: null
                });
            });
        }
    
        ngAfterViewInit(): void {
            // this.dataSource.paginator = this.paginator;
            // this.dataSource.sort = this.sort;
            for (let i = 0; i < this.tables.length; i++) {
                this.tables[i].dataSource.paginator = this.paginator.toArray()[i];
                this.tables[i].dataSource.sort = this.sort.toArray()[i];
            }
        }
    
        // dataSource is a parameter here
        applyFilter(event: Event, dataSource: any) {
            const filterValue = (event.target as HTMLInputElement).value;
            dataSource.filter = filterValue.trim().toLowerCase();
            if (dataSource.paginator) {
                dataSource.paginator.firstPage();
            }
        }
    }
    
    export interface PeriodicElement {
        name: string;
        position: number;
        weight: number;
        symbol: string;
        description: string;
    }
    
    const ELEMENT_DATA: PeriodicElement[] = [
        {
            position: 1,
            name: 'Hydrogen',
            weight: 1.0079,
            symbol: 'H',
            description: `Hydrogen is a chemical element with symbol H and atomic number 1. With a standard
                atomic weight of 1.008, hydrogen is the lightest element on the periodic table.`
        }, {
            position: 2,
            name: 'Helium',
            weight: 4.0026,
            symbol: 'He',
            description: `Helium is a chemical element with symbol He and atomic number 2. It is a
                colorless, odorless, tasteless, non-toxic, inert, monatomic gas, the first in the noble gas
                group in the periodic table. Its boiling point is the lowest among all the elements.`
        }, {
            position: 3,
            name: 'Lithium',
            weight: 6.941,
            symbol: 'Li',
            description: `Lithium is a chemical element with symbol Li and atomic number 3. It is a soft,
                silvery-white alkali metal. Under standard conditions, it is the lightest metal and the
                lightest solid element.`
        }, {
            position: 4,
            name: 'Beryllium',
            weight: 9.0122,
            symbol: 'Be',
            description: `Beryllium is a chemical element with symbol Be and atomic number 4. It is a
                relatively rare element in the universe, usually occurring as a product of the spallation of
                larger atomic nuclei that have collided with cosmic rays.`
        }, {
            position: 5,
            name: 'Boron',
            weight: 10.811,
            symbol: 'B',
            description: `Boron is a chemical element with symbol B and atomic number 5. Produced entirely
                by cosmic ray spallation and supernovae and not by stellar nucleosynthesis, it is a
                low-abundance element in the Solar system and in the Earth's crust.`
        }, {
            position: 6,
            name: 'Carbon',
            weight: 12.0107,
            symbol: 'C',
            description: `Carbon is a chemical element with symbol C and atomic number 6. It is nonmetallic
                and tetravalent—making four electrons available to form covalent chemical bonds. It belongs
                to group 14 of the periodic table.`
        }, {
            position: 7,
            name: 'Nitrogen',
            weight: 14.0067,
            symbol: 'N',
            description: `Nitrogen is a chemical element with symbol N and atomic number 7. It was first
                discovered and isolated by Scottish physician Daniel Rutherford in 1772.`
        }, {
            position: 8,
            name: 'Oxygen',
            weight: 15.9994,
            symbol: 'O',
            description: `Oxygen is a chemical element with symbol O and atomic number 8. It is a member of
                the chalcogen group on the periodic table, a highly reactive nonmetal, and an oxidizing
                agent that readily forms oxides with most elements as well as with other compounds.`
        }, {
            position: 9,
            name: 'Fluorine',
            weight: 18.9984,
            symbol: 'F',
            description: `Fluorine is a chemical element with symbol F and atomic number 9. It is the
                lightest halogen and exists as a highly toxic pale yellow diatomic gas at standard
                conditions.`
        }, {
            position: 10,
            name: 'Neon',
            weight: 20.1797,
            symbol: 'Ne',
            description: `Neon is a chemical element with symbol Ne and atomic number 10. It is a noble gas.
                Neon is a colorless, odorless, inert monatomic gas under standard conditions, with about
                two-thirds the density of air.`
        },
    ];
    

    HTML

    <!-- adding loop -->
    <ng-container *ngFor="let table of tables; index as tableIndex;">
    
        <mat-form-field>
            <mat-label>Filter</mat-label>
            <!-- updating applyFilter with current table's dataSource parameter -->
            <input matInput (keyup)="applyFilter($event, table.dataSource)" placeholder="Ex. Mia">
        </mat-form-field>
    
        <!-- using current table's dataSource -->
        <table mat-table [dataSource]="table.dataSource" multiTemplateDataRows matSort>
    
            <!-- using current table's columnsToDisplay -->
            <ng-container matColumnDef="{{column}}" *ngFor="let column of table.columnsToDisplay">
                <th mat-header-cell *matHeaderCellDef mat-sort-header> {{column}} </th>
                <td mat-cell *matCellDef="let element"> {{element[column]}} </td>
            </ng-container>
    
            <ng-container matColumnDef="expandedDetail">
            <!-- using current table's columnsToDisplay -->
                <td mat-cell *matCellDef="let element" [attr.colspan]="table.columnsToDisplay.length">
                    <!-- using current table's expandedElement -->
                    <div class="table-element-detail" [@detailExpand]="element == table.expandedElement ? 'expanded' : 'collapsed'">
                        <div class="table-element-diagram">
                            <div class="table-element-position"> {{element.position}} </div>
                            <div class="table-element-symbol"> {{element.symbol}} </div>
                            <div class="table-element-name"> {{element.name}} </div>
                            <div class="table-element-weight"> {{element.weight}} </div>
                        </div>
                        <div class="table-element-description">
                            {{element.description}}
                            <span class="table-element-description-attribution"> -- Wikipedia </span>
                        </div>
                    </div>
                </td>
            </ng-container>
    
            <!-- using current table's columnsToDisplay -->
            <tr mat-header-row *matHeaderRowDef="table.columnsToDisplay"></tr>
            <!-- using current table's columnsToDisplay and expandedElement -->
            <tr mat-row *matRowDef="let element; columns: table.columnsToDisplay;" class="table-element-row"
            [class.table-expanded-row]="table.expandedElement === element"
            (click)="table.expandedElement = table.expandedElement === element ? null : element">
            </tr>
            <tr mat-row *matRowDef="let row; columns: ['expandedDetail']" class="table-detail-row"></tr>
    
        </table>
    
        <mat-paginator [pageSizeOptions]="[5, 10, 25, 100]"></mat-paginator>
    
    </ng-container>
    

    如果分页器和排序是顺序的,上面的代码就可以工作。如果它们不是并且在两者之间使用了任何其他分页器或排序,这将失败。为防止这种情况发生,您可以为它们设置动态 ID,然后将它们分配给相应的数据源。

    还有其他方法可以做同样的事情。例如使用另一个具有表格和component-interaction 的组件。但这将要求您的表遵循相同的数据结构,或者主要取决于您如何使用它。

    【讨论】:

      猜你喜欢
      • 2018-06-22
      • 1970-01-01
      • 1970-01-01
      • 2021-05-30
      • 2018-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-03
      • 1970-01-01
      相关资源
      最近更新 更多