Angular 2 + ngrx(redux) + forms Angular 2 + ngrx(redux) + forms angular angular

Angular 2 + ngrx(redux) + forms


I have created a library called ngrx-forms that does exactly what you want. You can get it on npm via:

npm install ngrx-forms --save

I recommend checking out the full README on the github page, but below you can find some examples of what you need to do to get the library up and running once installed.

Import the module:

import { StoreModule } from '@ngrx/store';import { NgrxFormsModule } from 'ngrx-forms';import { reducers } from './reducer';@NgModule({  declarations: [    AppComponent,  ],  imports: [    NgrxFormsModule,    StoreModule.forRoot(reducers),  ],  providers: [],  bootstrap: [AppComponent]})export class AppModule { }

Add a group state somewhere in your state tree via createFormGroupState and call the formGroupReducer inside your reducer:

import { Action } from '@ngrx/store';import { FormGroupState, createFormGroupState, formGroupReducer } from 'ngrx-forms';export interface MyFormValue {  someTextInput: string;  someCheckbox: boolean;  nested: {    someNumber: number;  };}const FORM_ID = 'some globally unique string';const initialFormState = createFormGroupState<MyFormValue>(FORM_ID, {  someTextInput: '',  someCheckbox: false,  nested: {    someNumber: 0,  },});export interface AppState {  someOtherField: string;  myForm: FormGroupState<MyFormValue>;}const initialState: AppState = {  someOtherField: '',  myForm: initialFormState,};export function appReducer(state = initialState, action: Action): AppState {  const myForm = formGroupReducer(state.myForm, action);  if (myForm !== state.myForm) {    state = { ...state, myForm };  }  switch (action.type) {    case 'some action type':      // modify state      return state;    default: {      return state;    }  }}

Expose the form state inside your component:

import { Component } from '@angular/core';import { Store } from '@ngrx/store';import { FormGroupState } from 'ngrx-forms';import { Observable } from 'rxjs/Observable';import { MyFormValue } from './reducer';@Component({  selector: 'my-component',  templateUrl: './my-component.html',})export class MyComponent {  formState$: Observable<FormGroupState<MyFormValue>>;  constructor(private store: Store<AppState>) {    this.formState$ = store.select(s => s.myForm);  }}

Set the control states in your template:

<form novalidate [ngrxFormState]="(formState$ | async)">  <input type="text"         [ngrxFormControlState]="(formState$ | async).controls.someTextInput">  <input type="checkbox"         [ngrxFormControlState]="(formState$ | async).controls.someCheckbox">  <input type="number"         [ngrxFormControlState]="(formState$ | async).controls.nested.controls.someNumber"></form>


This is a fairly old question, but I couldn't find a great solution in my own quest for working with ngrx + reactive forms in Angular. As a result, I'll post my research here with hope that it may help someone else. My solution can be broken down into two parts, and I pray you (oh weathered soul) find it applicable to your problem:

1) Monitor the form element/s (for example, "keyup" event for a typical text input), and update the State from that event. This strategy comes straight out of the book search component in the ngrx example app. We can now successfully populate the State as our form changes. Awesome! 50% done!

2) The angular reactive forms guide demonstrates creating the form group in the constructor. I have seen some other people do it inside ngOnInit, but this is too late in the lifecycle for our needs (I tried, I failed). Now that we have our form group established, setup ngOnChanges to capture any changes pushed from the state, and then update the form group using patchValue. For example:

  ngOnChanges(changes: SimpleChanges) {    if (changes.valueICareAbout1) {      this.myForm.patchValue({        valueICareAbout1: changes.valueICareAbout1.currentValue      });    }    if (changes.valueICareAbout2) {      this.myForm.patchValue({        valueICareAbout2: changes.valueICareAbout2.currentValue      });    }  }


In the applications I built with Angular 2, the following guideline seemed to work well:

Parent components pass data down to children via data binding. Child components request data changes by emitting output events to parent components. It is the parent components responsibility to act accordingly.

In a hierarchical component structure, data changes are handled by the lowest component that depends on the data. If there's another component higher up or a sibling that depends on the same data item, pass changes up by emitting events and leave the handling to a higher component.

This scheme works well because, for any data that is relevant to more than one component, there is a single component responsible for performing changes. Changes bubble down automatically. Components are reusable, and changes in the component tree can be easily adapted.

With regard to validation, any component in the ladder between the lowest component emitting a data change request up to the highest component that finally handles the change, any component can effectively cancel the change by not passing it higher up. In most applications, I'd opt for validating data changes at the origin of the change though.

Naturally, child components can still have internal state and need not communicate changes - unless changes are relevant to the parent component.