【问题标题】:How to stop ngrx-forms reinitializing actions?如何停止 ngrx-forms 重新初始化操作?
【发布时间】:2020-04-22 06:58:03
【问题描述】:

[本题基于https://ngrx-forms.readthedocs.io/]

我的角度组件中有一组主题(字符串)。我正在使用 ngrx-store 来管理状态以及用于管理表单的 ngrx-forms。 在组件的初始化过程中,我为组件内的每个主题调度了一些动作。


 ngOnInit(): void {
    this.formState$ = this.store.pipe(select(s => s.filterByTopics.formState))
    this.topicsOptions$ = this.store.pipe(select(s => s.filterByTopics.topicsOptions))
    Object.keys(this.topics).forEach(topic => this.store.dispatch(new CreateTopicControlAction(topic)))
  }

效果很好,并且正在添加 ngrx-form 控件。

但真正的问题是,如果我再次访问同一个组件,它会重新初始化操作(因为 ngOnInit 包含所有操作)并吐出错误:

Uncaught Error: Group 'filterByTopicsForm.topics' already has child control '0'!

image.png

如何防止这种情况发生?

还有其他解决方法吗?

【问题讨论】:

    标签: angular forms ngrx angular-forms


    【解决方案1】:

    ngrx-forms 的作者在这里。

    这不是 ngrx-forms 本身的问题,而是一个更普遍的问题,即当状态在存储中时如何防止双重初始化,因此与组件的生命周期无关。

    我在这里看到了多个选项:

    1. 重置ngOnDestroy 中的表单,方法是调度带有初始值的SetValueAction 以及ResetAction(或创建您自己的自定义操作以在reducer 中重新创建表单状态);这模拟了@angular/forms 的行为,其中表单的存在时间与拥有组件的时间一样长;这是使用 ngrx v8+ 的自定义操作后的样子:

      const resetMyForm = createAction('MY_FORM/reset');
      
      const myFormReducer = createReducer(
        {
          formState: createFormGroupState('MY_FORM', INITIAL_FORM_VALUE),
        },
        onNgrxForms(),
        on(resetMyForm, ({ formState }, { lang, code }) => ({
          formState: createFormGroupState('MY_FORM', INITIAL_FORM_VALUE),
        })),
      );
      
    2. 检查表单是否已经在组件中初始化

      ngOnInit(): void {
        this.formState$ = this.store.pipe(select(s => s.filterByTopics.formState))
        this.topicsOptions$ = this.store.pipe(select(s => s.filterByTopics.topicsOptions))
        Object.keys(this.topics).forEach(topic => {
          this.formState$.pipe(take(1)).subscribe(formState => {
            // how exactly this `if` looks like depends on your concrete form state shape
            if (!formState.controls.topics.controls[topic]) {
              this.store.dispatch(new CreateTopicControlAction(topic))
            }
          })
        })
      }
      
    3. 检查表单是否已经在reducer中初始化

      const createTopicControl = createAction('MY_FORM/createTopicControl', (topic: string) => ({ topic }));
      
      const myFormReducer = createReducer(
        {
          formState: createFormGroupState('MY_FORM', INITIAL_FORM_VALUE),
        },
        onNgrxForms(),
        on(createTopicControl, (state, { topic }) => {
          if (state.formState.controls.topics.controls[topic]) {
            return state
          }
      
          // add form control ...
        }),
      );
      

    我希望这会有所帮助。

    【讨论】:

    • 我还有两个问题。你也能回答一下吗?
    猜你喜欢
    • 1970-01-01
    • 2017-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-20
    • 1970-01-01
    • 2012-12-22
    • 2016-06-26
    相关资源
    最近更新 更多