You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 08:10:11