Skip to content

Instantly share code, notes, and snippets.

@abdulhaq-e
Last active July 11, 2018 17:33
Show Gist options
  • Save abdulhaq-e/b0abc305c16f6c14b499ccfcd56459ed to your computer and use it in GitHub Desktop.
Save abdulhaq-e/b0abc305c16f6c14b499ccfcd56459ed to your computer and use it in GitHub Desktop.
Implementation of redux forms for angular 2 based on react redux forms.

These are just ideas on implementing forms using ngrx tools. The whole idea is based on react-redux-forms: http://redux-form.com/

NgrxFormsField

@Component({
  selector: `ngrx-forms-field`
  template: ``
})
class NgrxFormsField {
  constructor() {
    // some magic here that uses the Field "component" input to fill the template
  }
  // these define the field
  @Input() name: String;
  @Input() component: Component | function | String;
  @Input() validate: (value, allValues) => Error | undefined;
  @Input() warn: (value, allValues) => Warning | undefined;
  
  // field event
  @Input() onBlur: () => void;
  @Input() onChange: () => void;
  @Input() onDragStart: (event: Event) => void;
  @Input() onDrop: (event: Event) => void;
  @Input() onFocus: (event: Event) => void;
  @Input() value: string | boolean;
  
  // field status
  @Input() isActive: boolean
  @Input() is autoFilled: boolean
  @Input() isAsyncValidating: boolean
  @Input() isDirty: boolean
  @Input() error: Error;
  @Input() warning: Warning;
  @Input() isInvalid: boolean;
  @Input() isValid: boolean;
  @Input() isSubmitting: boolean;
}
@Component({
  selector: 'ngrx-forms',
})
class NgrxForms {

  constructor(private store: Store) {}
  
  @Input() handleSubmit: (data: any) => void;
  @Input() initialValues: any;
  @Input() initialise: (data: any) => void;
  @Input() validate: () => any;
  @Input() asyncValidate: () => any;
  @Input() warn: () => any;

  // and lots of other inputs: see http://redux-form.com/6.4.3/docs/api/Props.md/
}

NgrxFormActions

import { Action } from '@ngrx/store';

export class InitializeForm {
  type = 'INITIALIZE_FORM'
  constructor(payload: any) {}
  // payload should be an object containing the form name and initial values plus some other stuff
}

export class TouchField {
  type = 'TOUCH_FIELD'
  constructor(payload: any) {}
  // payload should be an object containing the form name and a list of fields to touch
}

export class SubmitForm {
  type = 'SUBMIT_FORM'
  constructor(payload: any) {}
  // payload consists of form name
}

// and a whole lot of other actions

NgrxFormsReducer

export function NgrxFormsReducer(state: NgrxFormsStore = initialNgrxFormsState,
  action: Action) {
  // handle all actions here
 }

By seeing how the reducers are implemented, it can be seen what is saved in the state. Everything is stored!, here are the important things:

store = {
  otherState: {},
  forms: {
    simpleForm: {
      fields: {
        firstName: { touched: true, autofilled: false, visisted: true, active: false},
      }
      initial: { firstName: 'Smith' },
      values: { firstName: 'Smith' },
      asyncErrors: {},
      syncErrors: {}
      submitErrors: { firstName: '' },
      anyTouched: true,
      submitting: false,
    }
  }
}

Let's see how a simple form can be made:

@Component({
  selector: 'simple-form',
  template: `
    <form #f (submit)="handleSubmit(#f)">
      <ngrx-forms-field name="firstName" component="firstNameField" label="First Name">
      </ngrx-forms-field>
    </form>
   `
})
class SimpleForm extends NgrxForms{
  constructor() {}
}

@Component({
  selector: 'smart-component',
  template: `<simple-form [handleSubmit]="doWhatever" [initialValues]="initialData"></simple-form>`
})
class SmartComponent {
  constructor() {}
  
  doWhatever() {
  }
  
  // initialData = ...
  
}

Now what remains in this psuedo-code is connecting the SimpleForm to the Store. Redux-Forms uses a decorator called reduxForm() (http://redux-form.com/6.4.3/docs/api/ReduxForm.md/) which the form component (the dumb component) is given as its arguments. This decorator does all the magic of storing the form state in the store. This includes dispatching actions and so on. This can be found here https://github.com/erikras/redux-form/blob/master/src/reduxForm.js . I don't fully understand it as there is too much react in it which I do not know much about.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment