如何停止 ngrx-forms 重新初始化操作?
How to stop ngrx-forms reinitializing actions?
[此题基于https://ngrx-forms.readthedocs.io/]
我的 angular 组件中有一组主题(字符串)。我使用 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 表单控件。
但真正的问题是,如果我再次访问同一个组件,它会重新初始化操作(因为 ngOnInit 包含所有操作)并吐出一个错误:
Uncaught Error: Group 'filterByTopicsForm.topics' already has child control '0'!
image.png
我怎样才能避免这种情况?
还有其他解决方法吗?
这里是 ngrx-forms 的作者。
这不是 ngrx-forms 本身的问题,而是一个更普遍的问题,即当状态在存储中时如何防止双重初始化,因此不耦合到组件的生命周期。
我在这里看到多个选项:
通过分派具有初始值的 SetValueAction
和 ResetAction
来重置 ngOnDestroy
中的表单(或创建您自己的自定义操作以重新创建在减速器中形成状态);这模拟了 @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),
})),
);
检查表单是否已经在组件中初始化
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))
}
})
})
}
检查表单是否已经在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 ...
}),
);
希望对您有所帮助。
[此题基于https://ngrx-forms.readthedocs.io/]
我的 angular 组件中有一组主题(字符串)。我使用 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 表单控件。
但真正的问题是,如果我再次访问同一个组件,它会重新初始化操作(因为 ngOnInit 包含所有操作)并吐出一个错误:
Uncaught Error: Group 'filterByTopicsForm.topics' already has child control '0'!
image.png
我怎样才能避免这种情况?
还有其他解决方法吗?
这里是 ngrx-forms 的作者。
这不是 ngrx-forms 本身的问题,而是一个更普遍的问题,即当状态在存储中时如何防止双重初始化,因此不耦合到组件的生命周期。
我在这里看到多个选项:
通过分派具有初始值的
SetValueAction
和ResetAction
来重置ngOnDestroy
中的表单(或创建您自己的自定义操作以重新创建在减速器中形成状态);这模拟了 @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), })), );
检查表单是否已经在组件中初始化
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)) } }) }) }
检查表单是否已经在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 ... }), );
希望对您有所帮助。