[этот вопрос основан на странице 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'!
Как я могу предотвратить это?
Есть ли другой обходной путь?
1 ответ
Автор ngrx-форм здесь.
Это не проблема ngrx-forms как таковая, а скорее общий вопрос о том, как предотвратить двойную инициализацию, когда состояние находится в хранилище и, следовательно, не связано со временем жизни компонента.
Я вижу здесь несколько вариантов:
сбросить форму в
ngOnDestroy
, отправивSetValueAction
с начальным значением, а такжеResetAction
(или создайте собственное действие для воссоздания состояния формы в редукторе); это имитирует поведение @ 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)) } }) }) }
Проверьте, инициализирована ли форма в редукторе
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 ... }), );
Надеюсь, это поможет.
Похожие вопросы
Новые вопросы
angular
Вопросы по Angular (не путать с AngularJS), веб-фреймворку от Google. Используйте этот тег для угловых вопросов, которые не относятся к конкретной версии. Для более старой веб-платформы AngularJS (1.x) используйте тег angularjs.