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

如何在@ngrx/store中存储状态并保留Angular表单数据?

解决Angular步骤切换时表单数据丢失问题

问题根源

当前NgRx仅维护了步骤切换的状态,但表单数据未被持久化到Store中。当通过ng-container切换组件时,组件会被销毁重建,导致表单数据重置。另外,SharedService中获取步骤的选择器路径错误,应该选择currentStep而非step。

具体修复步骤

1. 更新AppState与Actions

首先扩展状态模型,加入表单数据字段,并创建对应的更新动作:

app.actions.ts

import { createAction, props } from '@ngrx/store';
import { Step } from './main';

export const setCurrentStep = createAction(
  '[App] Set Current Step',
  props<{ step: Step }>()
);

// 添加更新表单数据的action
export const updateFormData = createAction(
  '[App] Update Form Data',
  props<{ formData: any }>() // 建议替换为具体的表单数据类型,比如interface FormData { name: string; email: string; }
);

app.state.ts

import { Step } from './main';

// 定义表单数据的接口,替换为实际的表单字段
export interface FormData {
  // 示例字段,根据实际表单调整
  name: string;
  email: string;
}

export interface AppState {
  currentStep: Step;
  formData: FormData; // 添加表单数据状态
}

2. 更新Reducer处理表单数据

修改reducer,初始化表单数据,并处理updateFormData动作:

app.reducer.ts

import { createReducer, on } from '@ngrx/store';
import { setCurrentStep, updateFormData } from './app.actions';
import { AppState, FormData } from './app.state';
import { Step } from './main';

// 初始化表单数据
const initialFormData: FormData = {
  name: '',
  email: ''
};

export const initialState: AppState = {
  currentStep: 1,
  formData: initialFormData
};

export const appReducer = createReducer(
  initialState,
  on(setCurrentStep, (state, { step }) => ({
    ...state,
    currentStep: step,
  })),
  // 添加处理表单数据更新的逻辑
  on(updateFormData, (state, { formData }) => ({
    ...state,
    formData: { ...state.formData, ...formData } // 合并更新,保留原有字段
  }))
);

3. 修正SharedService的选择器并添加表单数据方法

修复步骤选择器的错误路径,同时添加操作表单数据的方法:

shared-service.service.ts

import { Injectable } from '@angular/core';
import { Store, select } from '@ngrx/store';
import { AppState, FormData } from './app.state';
import { Observable } from 'rxjs';
import { setCurrentStep, updateFormData } from './app.actions';
import { Step } from './main';

@Injectable()
export class SharedServiceService {
  constructor(private store: Store<AppState>) {}

  setCurrentStep(step: Step) {
    this.store.dispatch(setCurrentStep({ step }));
  }

  // 修复选择器路径,改为currentStep
  getCurrentStep(): Observable<Step> {
    return this.store.pipe(select(state => state.currentStep));
  }

  // 添加更新表单数据的方法
  updateFormData(formData: Partial<FormData>) {
    this.store.dispatch(updateFormData({ formData }));
  }

  // 添加获取表单数据的方法
  getFormData(): Observable<FormData> {
    return this.store.pipe(select(state => state.formData));
  }
}

4. 在Comp1组件中绑定表单数据到Store

修改Comp1组件,在表单数据变化时同步到Store,初始化时从Store加载数据:

comp-1.component.ts

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
import { SharedServiceService } from 'src/shared-service.service';
import { FormData } from 'src/app.state';

@Component({
  selector: 'app-comp-1',
  templateUrl: './comp-1.component.html',
})
export class Comp1Component implements OnInit {
  form: FormGroup;

  constructor(
    private fb: FormBuilder,
    private sharedService: SharedServiceService
  ) {
    this.form = this.fb.group({
      name: [''],
      email: ['']
    });
  }

  ngOnInit(): void {
    // 从Store加载表单数据,回显到表单
    this.sharedService.getFormData().subscribe(formData => {
      this.form.patchValue(formData);
    });

    // 监听表单变化,同步到Store
    this.form.valueChanges.subscribe(formData => {
      this.sharedService.updateFormData(formData);
    });
  }

  goToNextStep() {
    this.sharedService.setCurrentStep(2);
  }
}

5. 可选优化:避免组件销毁

如果不想依赖Store持久化,也可以通过调整ng-container的渲染逻辑,使用[hidden]替代*ngIf,这样组件不会被销毁,数据会保留:

<ng-container [hidden]="currentStep !== 1">
  <app-comp-1></app-comp-1>
</ng-container>
<ng-container [hidden]="currentStep !== 2">
  <app-comp-2></app-comp-2>
</ng-container>

但这种方式会让组件始终存在于DOM中,对于复杂组件可能影响性能,推荐优先使用Store持久化的方案。


内容的提问来源于stack exchange,提问作者Netranjit Borgohain

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 09:32:04