Ручное обновление FormGroupState ngrx-форм отменяется при следующем изменении состояния

#angular #ngrx

#angular #ngrx

Вопрос:

В приложении Angular 12 мы используем NgRx с ngrx-формами. Начальное FormGroupState выглядит следующим образом:

 export const initialFormData = createFormGroupState<IFormData>('patientData', {
(..)
  birthday: {
    day: null,
    month: null,
    year: null,
  },
(..)
});
 

Это FormGroupState встроено в состояние, которое содержит все другие данные состояния:

 export const initialState: IState = {
  (..),
  formData: initialFormData,
  (..)
};
 

Управление FormData осуществляется с помощью атрибутов в html-шаблоне компонента:

 <mat-form-field>
  <mat-label>Tag</mat-label>
  <input matInput type="number" [ngrxFormControlState]="formState.controls.birthday.controls.day">
</mat-form-field>
<mat-form-field>
  <mat-label>Monat</mat-label>
  <select matNativeControl [ngrxFormControlState]="formState.controls.birthday.controls.month">
    (..)
  </select>
</mat-form-field>
<mat-form-field>
  <mat-label>Jahr</mat-label>
  <input matInput type="number" [ngrxFormControlState]="formState.controls.birthday.controls.year">
</mat-form-field>
 

Кроме того, formState реализован в основном редукторе NgRx:

const stateReducer = createReducer( initialState, onNgrxForms(), (..), );

Пока все работает по назначению, и любое обновление, которое пользователь вносит в эти поля формы, обновляется в состоянии:

изображение formState после обновления через ngrx-forms

Теперь, в одном экземпляре, мне нужно вручную установить это formState после действия пользователя (в данном случае, использование mat-календаря). Итак, я создал действие для этого случая, которое принимает год, месяц и день, каждый в виде числа:

 export const setDateOfBirth = createAction('[PatientData] setDateOfBirth',
  props<{ newYear: number, newMonth: number, newDay: number }>()
);
 

Реализация в редукторе выглядит следующим образом:

 const stateReducer = createReducer(
  initialState,
  onNgrxForms(),
  (..),
  on(setDateOfBirth, (state, {newYear, newMonth, newDay}) => ({
    ...state,
    formData: {
      ...state.formData,
      value: {
        ...state.formData.value,
        birthday: {...state.formData.value.birthday, year: newYear, month: newMonth, day: newDay}
      }
    },
  })),
);
 

Это также работает нормально, и состояние устанавливается на любые реквизиты, которые я передаю редуктору:

изображение formState после обновления вручную

Однако после установки значений вручную, как только любое другое изменение вносится в другое поле ввода, которое контролируется ngrx-form для этого formState, например, поле ввода для имени, formState мгновенно возвращается к последнему состоянию перед изменением вручную. Поле ввода выглядит следующим образом:

 <mat-form-field>
    <mat-label>Name</mat-label>
    <input matInput type="text" [ngrxFormControlState]="formState.controls.name">
</mat-form-field>
 

Я не уверен, почему это происходит, и, конечно, хотел бы предотвратить возврат к предыдущему состоянию. Если я запускаю несколько ручных настроек для formState, все они отменяются, как только [ngrxFormControlState] инициирует любое изменение формы.

Редактировать: я также нашел директиву ngrxFormsAction, которую, к сожалению, нельзя использовать с mat-calendar («Событие ngrxFormsAction не генерируется никакими применимыми директивами или элементом mat-calendar»).