UNPKG

redux-schema-form

Version:
268 lines (228 loc) 7.39 kB
![travis ci](https://travis-ci.org/buhichan/redux-schema-form.svg?branch=master) # Why 1. So that I don't have to write a component for every single `redux-form`. 2. Provide a per-field state that can be changed by form values at runtime, for example, hide or show a field based on another field's value. # Demo [Demo](https://stackblitz.com/edit/react-pnrkgw?file=index.js) # Deprecation - Previously had a widget theme for material-ui 1.0, but it's no longer maintained, should be deprecated. # Intro - Accept a `schema` prop to generate form. *Not* json schema but a self-invented one. :P - The state of the form is maintained by `redux-form` in `redux` state. - Pre-defined ant-design widget components so you don't have to write in every form. - number - text - password - email - date - file - checkbox - select - autocomplete - autocomplete-async - autocomplete-text - array - group - You can add more widgets using `addType`. - You can use custom buttons by using `setButtons` and `injectSubmittable` # How to use ``` //remember this component is just a wrapper around [redux-form](), so you have to add redux-form's reducer to make it work! import {ReduxSchemaForm,injectSubmittable} from "redux-schema-form" import "redux-schema-form/src/ant-design" const schema=[ { key:"name", label:"Name", type:"text", ...others// other props are passed to underlying component, such as required and multiLine },{ key:"password", label:"Password" type:"password" },{ key:"fieldWithState", label:"this field changed when Name changed", type:"text", listens:{ "Company Name":(value)=>{ if(value === 'Some Company') return { label:"Name Illegal" } else return { label:"this field changed when Name changed" } } } } ] function FormWithDefaultButtons(){ //Default buttons are chinese return <ReduxSchemaForm form="my-form" schema={schema} {...others} /> } const CustomSubmitButton = injectSubmittable({formName:"foo1",type:"submit"})(({props,children})=>{ return <button {...props}> {children} </button> }) const CustomResetForm = injectSubmittable({formName:"foo1",type:"reset"})(({props,children})=>{ return <button {...props}> {children} </button> }) function FormWithCustomButtons(){ return <div> <ReduxSchemaForm form="foo1" schema={schema} noButton {...others} /> <CustomSubmitButton>Submit Form</CustomSubmitButton> <CustomResetButton>Reset Fields</CustomResetButton> </div> } ``` # Limitation Performance? # API(props) All props are passed to the underlying `redux-form` instance, except these props: ## disableResubmit Form become not submittable if submit succeeded. ## noButton Hide submit and cancel buttons. ## children Children will be placed between form fields and buttons. ## schema Accepts an array of type `FormFieldSchema[]`: ```typescript import {BaseFieldProps} from "redux-form" export type Options = {name:string,value:string|number}[] export type AsyncOptions = ()=>Promise<Options> export type RuntimeAsyncOptions = (value:any)=>(Promise<Options>|Options) export type FieldSchamaChangeListeners={ /** * q:what is valuePath here? * a: * If your formValue is {"foo":{"haha":[{"bar":10032}]}}, then the callback here will receive these arguments: * 10032, {bar:10032}, [{bar:10032}], {haha:[{bar:10032}]}, {foo:...} */ [fieldKey:string]: (value?:any,formValue?:any,dispatch?:any)=>Partial<FormFieldSchema>|Promise<Partial<FormFieldSchema>>|void; }; export interface FormFieldSchema extends Partial<BaseFieldProps> { key:string, type: string | React.ComponentClass<WidgetProps> | React.StatelessComponent<WidgetProps>, label:string, hide?:boolean, placeholder?:string, fullWidth?:boolean, //todo: should I put this presentation logic here? required?:boolean, disabled?:boolean, multiple?:boolean, children?:FormFieldSchema[] options?:Options | AsyncOptions | RuntimeAsyncOptions, defaultValue?:any style?:React.CSSProperties, /** * keyPath will keyPath from the root of the form to your deeply nested field. e.g. foo.bar[1].far */ listens?:FieldSchamaChangeListeners| ((keyPath:string)=>FieldSchamaChangeListeners), valueCanChangeOnInitialze?:boolean /** * type: "file" only used in 'file' field * @returns string url * @theme mui/antd * @param file file to upload */ onFileChange?:(file:File|FileList)=>Promise<string>, downloadPathPrefix?:string, /** * type: "array" * @theme mui */ itemsPerRow?:number /** * type: "autocomplete-text/async/-" * @theme mui */ fullResult?:boolean /** * type: "autocomplete-async" * @theme mui */ throttle?:number showValueWhenNoEntryIsFound?:boolean /** * type: "select" * @theme mui/antd */ loadingText?:string, /** * type: "table-array/array" * @theme mui */ hideColumns?:string[] disableDelete?:boolean, disableCreate?:boolean, disableSort?:boolean, disableImport?:boolean /** * type: "table-array" * @theme mui */ disableFixSeparatorForExcel?:boolean //we must add sep=, as the first row to prevent excel to change the separator csvColumnSeparator?:string /** * type: "date/datetime" * @theme mui */ okLabel?:string cancelLabel?:string locale?:string data?:any, [rest:string]:any //the rest are passed to underlying widget component. } ``` - key The key of the field in the data, e.g. 'email' - label The displayed name of this field. e.g. 'Your Email:' - type The type of this field. e.g. 'select' or "text" or "email" - options Only meaningful if the type is "select" or "autocomplete-xxx", it must be an array of the type {name:string,value:any}, it defines the options of the selection component. - placeholder The hint text. - required As the name suggest. - disabled As the name suggest. - children Only meaningful if the type is "group" or "array". The resulted date will have an object as a property value. e.g. ```typescript const schema = [ { key:"g", type:"group", label:"group", children:[ { key:"name", type:"text", label:"Name" } ] } ] //The value passed to onSubmit will be like: {g:{name:"john"}} ``` - listens Object, the key is the keyPath of the field that is listened, when that field changed, the value which is a callback will be called by (current value,form value, redux dispatch), and the returned is a description of the change, which would be undefined or a partial FormFieldSchema, or a Promise of a partial FormFieldSchema. ``` - others All other fields in `FormFieldSchema` are passed to the underlying `redux-form`'s `Field` component. See their [docs](http://redux-form.com/).