ng-state
  • Introduction
  • Main differences
  • Getting Started
    • Instalation
    • Examples
  • Core concepts
    • Main idea
      • More complex flow visualization
    • Configuration
      • Immer Setup
      • ImmutableJs Setup
    • Store
      • Operators
      • Optimistic updates plugin
      • Optimistic updates plugin
      • Form manager plugin
        • onChange hook
        • shouldUpdateState hook
        • Custom form elements
      • Persist state plugin
        • Configuring custom storage
    • Actions
      • Immer
      • ImmutaleJs
      • Injectable Actions
    • Components with Actions
      • Signal Actions
      • State Actions
    • @InjectStore decorator
    • @WithStore decorator
    • @ComponentState decorator
    • Dispatcher
  • Different scenarios
    • Passing list item index via router
    • ngOnChanges hook
    • FormManager pitfalls
  • Unit testing
    • Setup
    • Test store
    • Test actions
    • Test component with actions
    • Test with Angular TestBed
  • Debugging
    • Setup
    • Redux DevTools
    • Automated changes output
    • Manual state changes check
    • Additional debugging information
  • Production
    • Production mode
    • Server Side Rendering (SSR)
  • Other information
    • Best practices
    • CLI
      • Custom Configurations
    • Performance
    • Blog Posts
    • Contributing
Powered by GitBook
On this page

Was this helpful?

  1. Different scenarios

FormManager pitfalls

Updating state property depending on other property using reactive forms

If you plan to update state property based on other form property for example: reset post code on house number change. When you type in hause number ipost code will reset but hause number input will remain unchanged. Please see code bellow

merge(
    this.form.controls.address.controls.addressSelectItem!.valueChanges,
    this.form.controls.address.controls.houseNr!.valueChanges,
)
    .pipe(
      safeTakeUntilDestroyed(this.destroyRef))
    .subscribe(() => {
        const addressSelectItemControl = this.form.controls.address.controls.addressSelectItem;
        const houseNrControl = this.form.controls.address.controls.houseNr;
        if (addressSelectItemControl?.dirty || houseNrControl?.dirty) {
            this.actions.resetPostalCode();
        }
    });
            
// actions code
resetPostalCode() {
    this.store.update((state) => {
        state.data.address.postalCode = '';
    });
}

Why did this happened? Because FormsManager has default debounceTime of 100ms before syncing form value to a state. Since post code state is updated before, so state update is synced first back to form with originl hause number value.

In order to fix that add debouncTime to code which will be greater that default FormsManager debounceTime

merge(
    this.form.controls.address.controls.addressSelectItem!.valueChanges,
    this.form.controls.address.controls.houseNr!.valueChanges,
)
    .pipe(
      debounceTime(150), // <----
      distinctUntilChanged(),
      safeTakeUntilDestroyed(this.destroyRef))
    .subscribe(() => {
        const addressSelectItemControl = this.form.controls.address.controls.addressSelectItem;
        const houseNrControl = this.form.controls.address.controls.houseNr;
        if (addressSelectItemControl?.dirty || houseNrControl?.dirty) {
            this.actions.resetPostalCode();
        }
    });

If 150ms seems to slow for you, you hav ealways a possibility to provide different debounceTime to FormsManager

this.ngFormStateManager = this.actions.store.select(['data'])
.form.bind(this.form, { 
    emitEvent: true,
    debounceTime: 50,
});
PreviousngOnChanges hookNextSetup

Last updated 6 months ago

Was this helpful?