Created
May 1, 2017 22:20
-
-
Save Aryk/5f69961736f4a546104587196d3ceab5 to your computer and use it in GitHub Desktop.
formHelper for react-redux-form
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Reducer } from 'redux'; | |
import { combineForms, FormState, FieldState } from 'react-redux-form'; | |
export interface IFormHelper<Model> { | |
modelPath: string; | |
attributePath: (fieldName: keyof Model) => string; | |
modelAttributePath: (fieldName: keyof Model) => string; | |
dataSelector: (store: any) => Model; | |
fieldMetaDataSelector: (store: any) => (field: keyof Model) => FieldState; | |
formMetaDataSelector: (store: any) => FormState; | |
formEntry: (initialStateOrReducer: Partial<Model> | Reducer<any>) => object; | |
} | |
/** | |
* We namespace everything form related under the 'form' reducer key, including the form states. The forms should not | |
* be where the model state is stored since forms are transient and can be cleared off and temporarily changed. | |
*/ | |
const reducerKeyName = 'form'; | |
const formMetaDataKey = 'fieldMeta'; | |
/** | |
* Creates nested forms for react-redux-form. The idea here is to have a nested heirarchy as such: | |
* | |
* form.video.title //=> 'My Favorite Video' | |
* form.fieldMeta.video.title //=> <field> | |
* form.fieldMeta.video.title.focus //=> true | |
* form.fieldMeta.video.title.touched //=> false | |
* | |
* Please read: https://davidkpiano.github.io/react-redux-form/docs/api/formReducer.html for more information about | |
* the <field> structure. | |
* | |
* The default heirarchy would name "fieldMeta" as "forms", which is kind of confusing since the "forms" namespace | |
* does not actually include the field value, only metadata about the form. | |
* | |
*/ | |
const formsReducerEntry = (forms: object) => ({ | |
[reducerKeyName]: combineForms(forms, reducerKeyName, {key: formMetaDataKey}), | |
}); | |
const formHelper = <Model>(formName: string): IFormHelper<Model> => { | |
const modelPath = [reducerKeyName, formName].join('.'); // ie form.user | |
// The signifance of this is that it allows us to check again the FieldNameType for matches. | |
const attributePath = fieldName => '.'.concat(fieldName); // ie .firstName | |
return { | |
modelPath, | |
modelAttributePath: fieldName => modelPath.concat(attributePath(fieldName)), // ie form.user.firstName | |
attributePath, | |
dataSelector: mainState => mainState[reducerKeyName][formName], | |
fieldMetaDataSelector: mainState => field => mainState[reducerKeyName][formMetaDataKey][formName][field], | |
formMetaDataSelector: mainState => mainState[reducerKeyName][formMetaDataKey][formName].$form, | |
/** | |
* Creates the entry to be put into the reducer where the key is the store key and value is the reducer. | |
*/ | |
formEntry: initialStateOrReducer => ({[formName]: initialStateOrReducer}), | |
}; | |
}; | |
export { formHelper, formsReducerEntry }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment