From 75b76c7fd74a2f50f68cd19ebd07658eb89edc81 Mon Sep 17 00:00:00 2001 From: jlison Date: Mon, 19 Aug 2019 19:30:43 -0700 Subject: [PATCH] fix: add custom react node inputs --- src/Form.tsx | 40 +++++++++++++++++++++++++++--------- src/components/Input.tsx | 5 ++++- src/interfaces/FormConfig.ts | 6 +++++- 3 files changed, 39 insertions(+), 12 deletions(-) diff --git a/src/Form.tsx b/src/Form.tsx index d67dbec..9a1e446 100644 --- a/src/Form.tsx +++ b/src/Form.tsx @@ -3,7 +3,7 @@ import useForm from 'react-hook-form'; import {useTranslation} from 'react-i18next'; import {Col, Form, Row} from 'reactstrap'; -import {FormConfig, FormHeader} from './interfaces/FormConfig'; +import {FormConfig, FormHeader, FormHooks} from './interfaces/FormConfig'; import fetch from './utils/fetch'; import InputForm from './components/Input'; import SelectForm from './components/SingleSelect'; @@ -16,6 +16,7 @@ interface Props { [key: string]: any; }; csrfUrl?: string; + getForm?: (formHooks: FormHooks) => any; onSubmit: (...args: any) => Promise | T | void; } @@ -27,7 +28,7 @@ const dependencies = [ ]; /** Form generator */ -export default ({csrfUrl, defaultValues, form, onSubmit}: Props) => { +export default ({csrfUrl, defaultValues, form, getForm, onSubmit}: Props) => { const formHooks = useForm({defaultValues}); const [csrf, setCsrf] = useState(); const {t} = useTranslation(); @@ -83,8 +84,8 @@ export default ({csrfUrl, defaultValues, form, onSubmit}: Props) => { {elementConfig.inputs.map((input, i) => { if ( - !mapper.hasOwnProperty(input.type) || - typeof (mapper as any)[input.type] !== 'function' + !mapper.hasOwnProperty(input.type as string) || + typeof (mapper as any)[input.type as string] !== 'function' ) { return null; } @@ -93,7 +94,7 @@ export default ({csrfUrl, defaultValues, form, onSubmit}: Props) => { - {(mapper as any)[input.type](input)} + {(mapper as any)[input.type as string](input)} ); })} @@ -106,18 +107,31 @@ export default ({csrfUrl, defaultValues, form, onSubmit}: Props) => { */ const renderInput = (elementConfig: FormConfig): React.ReactNode => ( - {(mapper as any)[elementConfig.type](elementConfig)} + + {(mapper as any)[elementConfig.type as string](elementConfig)} + ); + /** + * Render custom node as a form input. + * @param elementConfig Component/element form configuration object. + */ + const renderCustomNode = (elementConfig: FormConfig): React.ReactNode => ( + + {elementConfig.type} + + ); + /** * Render form element based on passed form config. * @param elementConfig Form configuration object to render form element. */ const renderElement = (elementConfig: FormConfig) => { if ( - !mapper.hasOwnProperty(elementConfig.type) || - typeof (mapper as any)[elementConfig.type] !== 'function' + typeof elementConfig.type === 'string' && + (!mapper.hasOwnProperty(elementConfig.type) || + typeof (mapper as any)[elementConfig.type] !== 'function') ) { return null; } @@ -128,10 +142,12 @@ export default ({csrfUrl, defaultValues, form, onSubmit}: Props) => { nodes.push(renderHeader(elementConfig.header)); } - if (elementConfig.inputs) { + if (typeof elementConfig.type === 'string' && !elementConfig.inputs) { + nodes.push(renderInput(elementConfig)); + } else if (elementConfig.inputs) { nodes.push(renderMultipleInputs(elementConfig)); } else { - nodes.push(renderInput(elementConfig)); + nodes.push(renderCustomNode(elementConfig)); } return ( @@ -153,6 +169,10 @@ export default ({csrfUrl, defaultValues, form, onSubmit}: Props) => { return onSubmit(data); }; + if (typeof getForm === 'function') { + getForm({...formHooks, csrf}); + } + return (
{form.map((elementConfig) => renderElement(elementConfig))} diff --git a/src/components/Input.tsx b/src/components/Input.tsx index d62f05e..7076da5 100644 --- a/src/components/Input.tsx +++ b/src/components/Input.tsx @@ -55,7 +55,10 @@ export default ({ {addon && ( - {addon.icon && <>{addon.icon}} + + {addon.icon && <>{addon.icon}}{' '} + {addon.text && <>{addon.text}} + )} { + csrf: string; +}