如何在Angular 4+NgRx环境下筛选Angular Material表格?
嘿,这个需求用NgRx来实现简直完美,毕竟所有数据都在本地,完全不用折腾服务器~ 我给你一步步拆解怎么搞:
实现本地州筛选的NgRx方案
1. 新增筛选相关的Action
首先在你的客户actions文件里加一个用来设置筛选州的action,让用户的选择能触发状态更新:
// customer.actions.ts import { Action } from '@ngrx/store'; import { Customer } from './customer.model'; export enum CustomerActionTypes { LoadCustomers = '[Customer] Load Customers', LoadCustomersSuccess = '[Customer] Load Customers Success', SetFilterState = '[Customer] Set Filter State' // 新增这个筛选action } export class SetFilterState implements Action { readonly type = CustomerActionTypes.SetFilterState; constructor(public payload: string | null) {} // payload存选中的州,null表示取消筛选 } export type CustomerActions = LoadCustomers | LoadCustomersSuccess | SetFilterState;
2. 更新Reducer的状态结构
原来的store里只有客户数组,现在需要加一个字段存当前的筛选状态,修改reducer:
// customer.reducer.ts import { CustomerActionTypes, CustomerActions } from './customer.actions'; import { Customer } from './customer.model'; export interface CustomerState { customers: Customer[]; filterState: string | null; // 新增筛选字段,null代表显示全部 } const initialState: CustomerState = { customers: [], filterState: null }; export function customerReducer(state = initialState, action: CustomerActions): CustomerState { switch (action.type) { case CustomerActionTypes.LoadCustomersSuccess: return { ...state, customers: action.payload }; case CustomerActionTypes.SetFilterState: return { ...state, filterState: action.payload // 更新筛选状态 }; default: return state; } }
3. 用Selector派生筛选后的客户列表
NgRx的Selector专门用来处理这种派生状态,写一个selector自动根据筛选条件过滤客户:
// customer.selectors.ts import { createSelector } from '@ngrx/store'; import { CustomerState } from './customer.reducer'; // 获取根状态里的customer模块状态(假设你的feature key是'customers') export const selectCustomerState = (state: any) => state.customers; // 获取原始的全部客户列表 export const selectAllCustomers = createSelector( selectCustomerState, (state: CustomerState) => state.customers ); // 获取当前的筛选州 export const selectFilterState = createSelector( selectCustomerState, (state: CustomerState) => state.filterState ); // 核心:生成筛选后的客户列表 export const selectFilteredCustomers = createSelector( selectAllCustomers, selectFilterState, (customers, filterState) => { if (!filterState) return customers; // 没有筛选条件就返回全部 // 这里假设Customer对象的州字段是'state',根据你的实际字段调整 return customers.filter(customer => customer.state === filterState); } );
4. 组件里整合筛选逻辑和视图
组件只需要负责触发action和展示数据,用async管道自动订阅筛选后的列表:
组件TS:
// customer-list.component.ts import { Component } from '@angular/core'; import { Store } from '@ngrx/store'; import { Observable } from 'rxjs'; import { Customer } from '../customer.model'; import { SetFilterState } from '../customer.actions'; import { selectFilteredCustomers } from '../customer.selectors'; @Component({ selector: 'app-customer-list', templateUrl: './customer-list.component.html' }) export class CustomerListComponent { filteredCustomers$: Observable<Customer[]>; // 你的50个州列表,也可以从常量文件导入 states = ['AL', 'AK', 'AZ', 'AR', 'CA', 'CO', 'CT', 'DE', 'FL', 'GA', 'HI', 'ID', 'IL', 'IN', 'IA', 'KS', 'KY', 'LA', 'ME', 'MD', 'MA', 'MI', 'MN', 'MS', 'MO', 'MT', 'NE', 'NV', 'NH', 'NJ', 'NM', 'NY', 'NC', 'ND', 'OH', 'OK', 'OR', 'PA', 'RI', 'SC', 'SD', 'TN', 'TX', 'UT', 'VT', 'VA', 'WA', 'WV', 'WI', 'WY']; displayedColumns = ['name', 'address', 'state']; // 表格列定义 constructor(private store: Store) { // 订阅筛选后的客户列表 this.filteredCustomers$ = this.store.select(selectFilteredCustomers); } onStateSelected(selectedState: string | null) { // 用户选择州时,dispatch更新筛选状态的action this.store.dispatch(new SetFilterState(selectedState)); } }
组件HTML:
<!-- customer-list.component.html --> <!-- 州筛选下拉框 --> <mat-form-field class="filter-field"> <mat-label>筛选州</mat-label> <mat-select (selectionChange)="onStateSelected($event.value)" placeholder="全部客户"> <mat-option [value]="null">全部客户</mat-option> <mat-option *ngFor="let state of states" [value]="state">{{state}}</mat-option> </mat-select> </mat-form-field> <!-- 展示筛选后的表格 --> <table mat-table [dataSource]="filteredCustomers$ | async" class="mat-elevation-z8"> <!-- 姓名列 --> <ng-container matColumnDef="name"> <th mat-header-cell *matHeaderCellDef> 姓名 </th> <td mat-cell *matCellDef="let customer"> {{customer.name}} </td> </ng-container> <!-- 地址列 --> <ng-container matColumnDef="address"> <th mat-header-cell *matHeaderCellDef> 地址 </th> <td mat-cell *matCellDef="let customer"> {{customer.address}} </td> </ng-container> <!-- 州列 --> <ng-container matColumnDef="state"> <th mat-header-cell *matHeaderCellDef> 州 </th> <td mat-cell *matCellDef="let customer"> {{customer.state}} </td> </ng-container> <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> </table>
为什么这么做?
- 完全符合NgRx单向数据流的规则:用户操作→触发action→reducer更新状态→selector派生结果→视图自动更新
- 所有筛选逻辑都集中在store层,组件只负责展示和触发动作,保持组件简洁易维护
- 全程本地处理,不用请求服务器,完美利用已有的本地数据
内容的提问来源于stack exchange,提问作者mikeLong100
相关产品推荐
相关产品推荐

