Angular 14+ 用户详情Mat Data Table弹窗与导出功能实现需求
Angular 14+ Mat Data Table 功能实现方案
前置准备
- 确保已导入Angular Material的
MatDialogModule到你的模块中 - 安装导出依赖:
npm install xlsx papaparse
1. 模板修改(完整代码)
替换原有的mat-card内容,添加导出按钮、修改操作列点击事件、行点击事件:
<mat-card> <!-- 导出按钮组 --> <div class="d-flex justify-content-end mb-2"> <button mat-raised-button color="primary" (click)="exportToExcel()"> 导出Excel </button> <button mat-raised-button color="accent" class="ms-2" (click)="exportToCSV()"> 导出CSV </button> </div> <mat-form-field class="full-width py-2"> <input class="mt-1" matInput (keyup)="applyFilter($event)" placeholder="Search" #input /> </mat-form-field> <table mat-table [dataSource]="dataSource" class="mat-elevation-z8" matSort #empTbSort="matSort"> <ng-container matColumnDef="id"> <th mat-header-cell *matHeaderCellDef mat-sort-header >No.</th> <td mat-cell *matCellDef="let element">{{ element.id }}</td> </ng-container> <ng-container matColumnDef="name"> <th mat-header-cell *matHeaderCellDef mat-sort-header > Name </th> <td mat-cell *matCellDef="let element"> {{element.name}} </td> </ng-container> <ng-container matColumnDef="email"> <th mat-header-cell *matHeaderCellDef mat-sort-header > email </th> <td mat-cell *matCellDef="let element"> {{element.email}} </td> </ng-container> <ng-container matColumnDef="phone"> <th mat-header-cell *matHeaderCellDef mat-sort-header > phone </th> <td mat-cell *matCellDef="let element"> {{element.phone}} </td> </ng-container> <ng-container matColumnDef="company"> <th mat-header-cell *matHeaderCellDef mat-sort-header > company </th> <td mat-cell *matCellDef="let element"> {{element.company}} </td> </ng-container> <ng-container matColumnDef="actions"> <th mat-header-cell *matHeaderCellDef> actions </th> <td mat-cell *matCellDef="let element"> <button mat-button (click)="openSubordinateDialog(element)">Click here</button> </td> </ng-container> <ng-container matColumnDef="role"> <mat-header-cell *matHeaderCellDef> Role Name </mat-header-cell> <mat-cell *matCellDef="let row"> {{row.role}} </mat-cell> </ng-container> <tr mat-header-row *matHeaderRowDef ="displayedColumns"></tr> <tr (click)="openUserDetailDialog(emprow)" mat-row *matRowDef="let emprow; columns: displayedColumns"></tr> </table> <mat-paginator [pageSizeOptions]="[5, 10, 25, 100]"></mat-paginator> </mat-card>
2. 主组件逻辑(.ts文件)
import { Component, ViewChild } from '@angular/core'; import { MatSort } from '@angular/material/sort'; import { MatPaginator } from '@angular/material/paginator'; import { MatTableDataSource } from '@angular/material/table'; import { MatDialog } from '@angular/material/dialog'; import * as XLSX from 'xlsx'; import * as Papa from 'papaparse'; // 导入自定义弹窗组件(需要你自己创建) import { SubordinateDialogComponent } from './subordinate-dialog/subordinate-dialog.component'; import { UserDetailDialogComponent } from './user-detail-dialog/user-detail-dialog.component'; // 定义用户数据接口 export interface User { id: number; name: string; email: string; phone: string; company: string; role: string; // 额外信息字段 address?: string; website?: string; // 下属数据字段 subordinates?: { id: number; name: string; department: string }[]; } @Component({ selector: 'app-user-table', templateUrl: './user-table.component.html', styleUrls: ['./user-table.component.scss'] }) export class UserTableComponent { displayedColumns: string[] = ['id', 'name', 'email', 'phone', 'company', 'role', 'actions']; dataSource: MatTableDataSource<User>; @ViewChild(MatSort) sort!: MatSort; @ViewChild(MatPaginator) paginator!: MatPaginator; // 模拟数据,实际替换为你的接口数据 users: User[] = [ { id: 1, name: 'John Doe', email: 'john@example.com', phone: '123-456-7890', company: 'Tech Corp', role: 'Manager', address: '123 Main St, City', website: 'example.com', subordinates: [ { id: 101, name: 'Jane Smith', department: 'Dev' }, { id: 102, name: 'Bob Brown', department: 'Design' } ] }, // 更多用户数据... ]; constructor(private dialog: MatDialog) { this.dataSource = new MatTableDataSource(this.users); } ngAfterViewInit() { this.dataSource.sort = this.sort; this.dataSource.paginator = this.paginator; } applyFilter(event: Event) { const filterValue = (event.target as HTMLInputElement).value; this.dataSource.filter = filterValue.trim().toLowerCase(); } // 功能1:打开下属弹窗 openSubordinateDialog(user: User) { this.dialog.open(SubordinateDialogComponent, { width: '500px', data: user.subordinates || [] }); } // 功能2:导出Excel exportToExcel() { const worksheet = XLSX.utils.json_to_sheet(this.dataSource.data); const workbook = XLSX.utils.book_new(); XLSX.utils.book_append_sheet(workbook, worksheet, 'Users'); XLSX.writeFile(workbook, 'user-data.xlsx'); } // 功能2:导出CSV exportToCSV() { const csv = Papa.unparse(this.dataSource.data); const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' }); const url = URL.createObjectURL(blob); const link = document.createElement('a'); link.href = url; link.setAttribute('download', 'user-data.csv'); document.body.appendChild(link); link.click(); document.body.removeChild(link); } // 功能3:打开用户详情弹窗 openUserDetailDialog(user: User) { this.dialog.open(UserDetailDialogComponent, { width: '600px', data: user }); } }
3. 弹窗组件实现
下属弹窗组件(subordinate-dialog.component.ts)
import { Component, Inject } from '@angular/core'; import { MAT_DIALOG_DATA } from '@angular/material/dialog'; export interface Subordinate { id: number; name: string; department: string; } @Component({ selector: 'app-subordinate-dialog', templateUrl: './subordinate-dialog.component.html', }) export class SubordinateDialogComponent { constructor(@Inject(MAT_DIALOG_DATA) public data: Subordinate[]) {} }
对应的HTML:
<h2 mat-dialog-title>下属信息</h2> <mat-dialog-content> <table mat-table [dataSource]="data" class="mat-elevation-z2"> <ng-container matColumnDef="id"> <th mat-header-cell *matHeaderCellDef>ID</th> <td mat-cell *matCellDef="let element">{{element.id}}</td> </ng-container> <ng-container matColumnDef="name"> <th mat-header-cell *matHeaderCellDef>姓名</th> <td mat-cell *matCellDef="let element">{{element.name}}</td> </ng-container> <ng-container matColumnDef="department"> <th mat-header-cell *matHeaderCellDef>部门</th> <td mat-cell *matCellDef="let element">{{element.department}}</td> </ng-container> <tr mat-header-row *matHeaderRowDef="['id', 'name', 'department']"></tr> <tr mat-row *matRowDef="let row; columns: ['id', 'name', 'department']"></tr> </table> </mat-dialog-content> <mat-dialog-actions> <button mat-button mat-dialog-close>关闭</button> </mat-dialog-actions>
用户详情弹窗组件(user-detail-dialog.component.ts)
import { Component, Inject } from '@angular/core'; import { MAT_DIALOG_DATA } from '@angular/material/dialog'; import { User } from '../user-table/user-table.component'; @Component({ selector: 'app-user-detail-dialog', templateUrl: './user-detail-dialog.component.html', }) export class UserDetailDialogComponent { constructor(@Inject(MAT_DIALOG_DATA) public data: User) {} }
对应的HTML:
<h2 mat-dialog-title>{{data.name}} 详情</h2> <mat-dialog-content class="mat-typography"> <div class="detail-item"> <span class="label">邮箱:</span>{{data.email}} </div> <div class="detail-item"> <span class="label">电话:</span>{{data.phone}} </div> <div class="detail-item"> <span class="label">公司地址:</span>{{data.company}} - {{data.address}} </div> <div class="detail-item"> <span class="label">网站:</span>{{data.website}} </div> </mat-dialog-content> <mat-dialog-actions> <button mat-button mat-dialog-close>关闭</button> </mat-dialog-actions>
添加基础样式(可选):
.detail-item { margin: 10px 0; .label { font-weight: bold; margin-right: 8px; } }
4. 模块配置
确保在你的模块中导入并声明相关组件:
import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { MatTableModule } from '@angular/material/table'; import { MatSortModule } from '@angular/material/sort'; import { MatPaginatorModule } from '@angular/material/paginator'; import { MatFormFieldModule } from '@angular/material/form-field'; import { MatInputModule } from '@angular/material/input'; import { MatButtonModule } from '@angular/material/button'; import { MatDialogModule } from '@angular/material/dialog'; import { UserTableComponent } from './user-table/user-table.component'; import { SubordinateDialogComponent } from './subordinate-dialog/subordinate-dialog.component'; import { UserDetailDialogComponent } from './user-detail-dialog/user-detail-dialog.component'; @NgModule({ declarations: [ UserTableComponent, SubordinateDialogComponent, UserDetailDialogComponent ], imports: [ CommonModule, MatTableModule, MatSortModule, MatPaginatorModule, MatFormFieldModule, MatInputModule, MatButtonModule, MatDialogModule ], exports: [UserTableComponent] }) export class UserTableModule { }
内容的提问来源于stack exchange,提问作者Vijay Dhumale
相关产品推荐
相关产品推荐

