Angular 17中能否将基于Signal的数据源用于Material Table(mat-table)?
Angular 17中用Signal作为Material Table数据源的可行性及实现
完全可以将基于Signal的数据作为Angular Material Table的数据源,Angular 17搭配对应版本的@angular/material(>=17.0.0)已经原生支持这种用法。
直接绑定Signal返回值
你尝试的<table mat-table [dataSource]="store.users()">写法本身是可行的,只要Signal返回的是数组类型,表格就能正常渲染。当Signal的值更新时,只要确保更新操作触发了Signal的变化通知(比如用set设置新数组,或用mutate修改内部数组),表格会自动刷新。
示例代码:
定义Signal数据源
import { signal } from '@angular/core'; interface User { id: number; name: string; email: string; } export class UserStore { private _users = signal<User[]>([]); // 对外暴露只读Signal readonly users = this._users.asReadonly(); // 更新数据:传入新数组 setUsers(newUsers: User[]) { this._users.set(newUsers); } // 新增用户:通过mutate修改内部数组 addUser(user: User) { this._users.mutate(users => users.push(user)); } }
模板中绑定
<table mat-table [dataSource]="store.users()"> <!-- 定义列 --> <ng-container matColumnDef="name"> <th mat-header-cell *matHeaderCellDef> 用户名 </th> <td mat-cell *matCellDef="let user"> {{ user.name }} </td> </ng-container> <ng-container matColumnDef="email"> <th mat-header-cell *matHeaderCellDef> 邮箱 </th> <td mat-cell *matCellDef="let user"> {{ user.email }} </td> </ng-container> <!-- 表头和行渲染 --> <tr mat-header-row *matHeaderRowDef="['name', 'email']"></tr> <tr mat-row *matRowDef="let row; columns: ['name', 'email'];"></tr> </table>
结合MatTableDataSource使用(支持排序/过滤)
如果需要用到Material Table的排序、过滤等高级功能,可以将Signal的值同步到MatTableDataSource中,通过effect监听Signal变化来更新数据源:
import { Component, effect, inject } from '@angular/core'; import { MatTableDataSource } from '@angular/material/table'; import { UserStore } from './user.store'; @Component({ selector: 'app-user-table', templateUrl: './user-table.component.html', }) export class UserTableComponent { private userStore = inject(UserStore); displayedColumns = ['name', 'email']; dataSource = new MatTableDataSource<User>([]); constructor() { // 监听Signal变化,同步到数据源 effect(() => { this.dataSource.data = this.userStore.users(); }); } }
模板绑定示例:
<table mat-table [dataSource]="dataSource" matSort> <!-- 列定义 --> <ng-container matColumnDef="name"> <th mat-header-cell *matHeaderCellDef mat-sort-header> 用户名 </th> <td mat-cell *matCellDef="let user"> {{ user.name }} </td> </ng-container> <!-- 其他列... --> <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> </table>
注意事项
- 确保
@angular/material版本与Angular 17匹配(建议使用^17.0.0版本),避免版本不兼容导致的问题。 - 更新Signal数据时,要么传入新数组(
set方法),要么使用mutate修改内部数组,这样才能触发Signal的更新通知,让表格同步刷新。
内容的提问来源于stack exchange,提问作者Abdulaziz Ladan
相关产品推荐
相关产品推荐

