From a318ba74cef455956e5aeff69b3cd06061b929e7 Mon Sep 17 00:00:00 2001 From: Ray Arvin Rimorin Date: Thu, 13 May 2021 19:45:32 +0800 Subject: [PATCH 1/2] ZI-8112 nested form/ buggy deletes --- package.json | 2 +- src/components/FormBuilder/FormBuilder.js | 181 ++++++++----- src/components/FormBuilder/index.js | 4 +- src/components/FormBuilder/index.stories.js | 272 +++++++++++++++++--- yarn.lock | 19 +- 5 files changed, 360 insertions(+), 118 deletions(-) diff --git a/package.json b/package.json index 168ad3c..c7293d4 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,6 @@ "version": "0.6.8", "private": false, "dependencies": { - "@date-io/moment": "1.x", "@material-ui/core": "^4.11.3", "@material-ui/icons": "^4.11.2", @@ -20,6 +19,7 @@ "formik-material-ui": "^3.0.1", "formik-material-ui-lab": "^0.0.8", "formik-material-ui-pickers": "^0.0.12", + "lodash.get": "^4.4.2", "lodash.isempty": "^4.4.0", "luxon": "^1.26.0", "moment": "^2.29.1", diff --git a/src/components/FormBuilder/FormBuilder.js b/src/components/FormBuilder/FormBuilder.js index 257e8d7..b5e1b94 100644 --- a/src/components/FormBuilder/FormBuilder.js +++ b/src/components/FormBuilder/FormBuilder.js @@ -34,10 +34,16 @@ import { KeyboardTimePicker, MuiPickersUtilsProvider, } from "@material-ui/pickers"; -import { useFormik } from "formik"; -import { isEmpty } from "lodash"; +import { ErrorMessage, FieldArray, Formik, useFormik } from "formik"; +import { isEmpty, get } from "lodash"; import PropTypes from "prop-types"; -import React, { useCallback, useEffect, useMemo } from "react"; +import React, { + useCallback, + useContext, + useEffect, + useMemo, + useState, +} from "react"; import * as Yup from "yup"; const useStyles = makeStyles((theme) => ({ @@ -51,7 +57,7 @@ const useStyles = makeStyles((theme) => ({ }, })); -const FormBuilder = ({ +const FormFieldSet = ({ form, formLayout = [], formFactor = "default", @@ -60,46 +66,15 @@ const FormBuilder = ({ submitLabel = "Submit", resetLabel = "Reset", columns = 1, - onSubmit = () => {}, - readOnly, setValues = {}, - additionalActions, + additionalActions = () => {}, children, + isSubForm = true, + fieldArray, }) => { const classes = useStyles(); - const validationSchema = useMemo(() => { - const validatorMap = Object.fromEntries( - Object.entries(form) - .filter(([k, v]) => !!v.validator) - .map(([k, v]) => { - return [k, v.validator()]; - }) - ); - const validator = Yup.object().shape({ - ...validatorMap, - }); - return validator; - }, [form]); - const initialValues = useMemo(() => { - return Object.fromEntries( - Object.entries(form).map(([k, v]) => { - return [k, v.initialValues]; - }) - ); - }, [form]); - - const formik = useFormik({ - initialValues: initialValues, - validationSchema: validationSchema, - - onSubmit: (values) => { - setTimeout(() => { - formik.setSubmitting(false); - onSubmit(values); - }, 500); - }, - }); + const { formik, validationSchema, initialValues } = useContext(FormContext); useEffect(() => { if (!isEmpty(setValues)) { @@ -130,11 +105,13 @@ const FormBuilder = ({ name={fieldName} type={fieldParams.type} label={fieldParams.label} - value={formik.values[fieldName]} + value={get(formik.values, fieldName)} onChange={onChangeOverride} disabled={fieldParams.readOnly} error={ - formik.touched[fieldName] && Boolean(formik.errors[fieldName]) + get(formik.touched, fieldName) && + Boolean(get(formik.errors, fieldName)) + // formik.touched[fieldName] && Boolean(formik.errors[fieldName]) } InputLabelProps={{ shrink: true, @@ -151,7 +128,6 @@ const FormBuilder = ({ label={fieldParams.label} name={fieldName} onChange={(evt, val) => { - console.log("📢[FormBuilder.js:152]:", evt); if (fieldParams.onChange) { fieldParams.onChange( fieldName, @@ -163,7 +139,7 @@ const FormBuilder = ({ fieldParams.useLocalTime ? evt.local(true) : evt.utc(true) ); }} - value={formik.values[fieldName]} + value={get(formik.values, fieldName)} disabled={fieldParams.readOnly} autoOk format="MM/DD/yyyy" @@ -192,7 +168,7 @@ const FormBuilder = ({ fieldParams.useLocalTime ? evt.local(true) : evt.utc(true) ); }} - value={formik.values[fieldName]} + value={get(formik.values, fieldName)} disabled={fieldParams.readOnly} autoOk variant="inline" @@ -209,7 +185,6 @@ const FormBuilder = ({ label={fieldParams.label} name={fieldName} onChange={(evt, val) => { - console.log("📢[FormBuilder.js:181]:", evt, val); if (fieldParams.onChange) { fieldParams.onChange( fieldName, @@ -221,7 +196,7 @@ const FormBuilder = ({ fieldParams.useLocalTime ? evt.local(true) : evt.utc(true) ); }} - value={formik.values[fieldName]} + value={get(formik.values, fieldName)} disabled={fieldParams.readOnly} autoOk variant="inline" @@ -239,7 +214,7 @@ const FormBuilder = ({ name={fieldName} fullWidth label={fieldParams.label} - value={formik.values[fieldName]} + value={get(formik.values, fieldName)} onChange={onChangeOverride} multiple={fieldParams.settings.multiple} disabled={fieldParams.readOnly} @@ -265,7 +240,7 @@ const FormBuilder = ({ <> : } @@ -289,7 +264,7 @@ const FormBuilder = ({ @@ -316,7 +291,7 @@ const FormBuilder = ({ disableCloseOnSelect name={fieldName} label={fieldParams.label} - value={formik.values[fieldName]} + value={get(formik.values, fieldName)} onChange={(evt, val) => { if (fieldParams.onChange) { fieldParams.onChange(fieldName, val); @@ -335,8 +310,8 @@ const FormBuilder = ({ label={fieldParams.label} placeholder="type to search" error={ - formik.touched[fieldName] && - Boolean(formik.errors[fieldName]) + get(formik.touched, fieldName) && + Boolean(get(formik.errors, fieldName)) } fullWidth /> @@ -381,11 +356,16 @@ const FormBuilder = ({ className={classes.controlContainer} fullWidth component="fieldset" - error={formik.touched[layout] && Boolean(formik.errors[layout])} + error={ + // formik.touched[layout] && Boolean(formik.errors[layout]) + get(formik.touched, layout) && + Boolean(get(formik.errors, layout)) + } > {renderField(layout, field)} - {formik.touched[layout] && formik.errors[layout]} + {get(formik.touched, layout) && get(formik.errors, layout)} + {/* {formik.touched[layout] && formik.errors[layout]} */} @@ -414,7 +394,9 @@ const FormBuilder = ({ variant = "contained"; break; } - return ( + return isSubForm ? ( + <> + ) : ( + )} > - - ( - - + + + )} > - Nested - - - )} - /> + {(subform ?? []).map((x, subidx) => { + if (!x) { + return ; + } + return ( + ( + + + + )} + /> + ); + })} + + ) : ( + + ); + })} ); @@ -345,4 +507,32 @@ const NestedStory = ({ ...args }) => { export const Nested = NestedStory.bind({}); Nested.args = { ...Default.args, + + subformInitialValues: { + subform: [], + }, + subformValidator: { + subform: Yup.array().of( + Yup.object().shape({ + formfield1: Yup.string().nullable().required(), + formfield2: Yup.string().nullable().required(), + }) + ), + }, + subForm: [], + formLayout: ["form1", "form2"], + form: { + form1: { + type: "text", + label: "form 1", + initialValues: "a", + validator: () => Yup.string().nullable().required(), + }, + form2: { + type: "text", + label: "form 2", + initialValues: "b", + validator: () => Yup.string().nullable().required(), + }, + }, }; diff --git a/yarn.lock b/yarn.lock index 2e72d97..cb81660 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2172,20 +2172,6 @@ resolved "https://registry.yarnpkg.com/@date-io/core/-/core-1.3.13.tgz#90c71da493f20204b7a972929cc5c482d078b3fa" integrity sha512-AlEKV7TxjeK+jxWVKcCFrfYAk8spX9aCyiToFIiLPtfQbsjmRGLIhb5VZgptQcJdHtLXo7+m0DuurwFgUToQuA== -"@date-io/date-fns@1.x": - version "1.3.13" - resolved "https://registry.yarnpkg.com/@date-io/date-fns/-/date-fns-1.3.13.tgz#7798844041640ab393f7e21a7769a65d672f4735" - integrity sha512-yXxGzcRUPcogiMj58wVgFjc9qUYrCnnU9eLcyNbsQCmae4jPuZCDoIBR21j8ZURsM7GRtU62VOw5yNd4dDHunA== - dependencies: - "@date-io/core" "^1.3.13" - -"@date-io/luxon@1.x": - version "1.3.13" - resolved "https://registry.yarnpkg.com/@date-io/luxon/-/luxon-1.3.13.tgz#68f0134bb38ef486b2ed6df01981f814c633e28a" - integrity sha512-9wUrJCNSMZJeYAiH+dbb45oGpnHeFP7TOH/Lt26If47gjFCkjvyINzWx+K5AGsnlP0Qosxc7hkF1yLi6ecutxw== - dependencies: - "@date-io/core" "^1.3.13" - "@date-io/moment@1.x": version "1.3.13" resolved "https://registry.yarnpkg.com/@date-io/moment/-/moment-1.3.13.tgz#56c2772bc4f6675fc6970257e6033e7a7c2960f0" @@ -11027,6 +11013,11 @@ lodash.debounce@^4.0.8: resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= +lodash.get@^4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" + integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= + lodash.isempty@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.isempty/-/lodash.isempty-4.4.0.tgz#6f86cbedd8be4ec987be9aaf33c9684db1b31e7e" From 10959bc09ea1157155ac725a4e66b8fd7d2bdbb2 Mon Sep 17 00:00:00 2001 From: Ray Arvin Rimorin Date: Thu, 13 May 2021 20:20:22 +0800 Subject: [PATCH 2/2] ZI-8112 nested form with fieldarray --- src/components/FormBuilder/FormBuilder.js | 67 +++++++++++++++------ src/components/FormBuilder/index.stories.js | 16 +---- 2 files changed, 50 insertions(+), 33 deletions(-) diff --git a/src/components/FormBuilder/FormBuilder.js b/src/components/FormBuilder/FormBuilder.js index b5e1b94..44af633 100644 --- a/src/components/FormBuilder/FormBuilder.js +++ b/src/components/FormBuilder/FormBuilder.js @@ -14,6 +14,7 @@ import { FormHelperText, FormLabel, Grid, + IconButton, InputLabel, LinearProgress, ListItemText, @@ -26,7 +27,7 @@ import { TextField, Toolbar, } from "@material-ui/core"; -import { Backspace } from "@material-ui/icons"; +import { Backspace, DeleteForever } from "@material-ui/icons"; import { Autocomplete } from "@material-ui/lab"; import { KeyboardDatePicker, @@ -71,6 +72,7 @@ const FormFieldSet = ({ children, isSubForm = true, fieldArray, + index }) => { const classes = useStyles(); @@ -382,7 +384,8 @@ const FormFieldSet = ({ ); }, [buildComponent, columns, form, formLayout]); - const buildFormFactor = useMemo(() => { + const buildFormFactor = (arrayHelpers) => { + console.log("📢[FormBuilder.js:385]:", arrayHelpers); const ActionButtons = () => { let variant = ""; switch (formFactor) { @@ -425,7 +428,20 @@ const FormFieldSet = ({ + {additionalActions()} + {!arrayHelpers || ( + { + debugger; + }} + > + + + )} + + } /> {buildFields()} @@ -443,7 +459,19 @@ const FormFieldSet = ({ - {additionalActions()} + + {additionalActions()} + {!arrayHelpers || ( + { + arrayHelpers.replace(index, undefined) + console.log("📢[FormBuilder.js:466]:", arrayHelpers, index); + }} + > + + + )} + {buildFields()} @@ -461,24 +489,23 @@ const FormFieldSet = ({ {formik.isSubmitting && }
- {additionalActions()} + + {additionalActions()} + {!arrayHelpers || ( + { + debugger; + }} + > + + + )} +
); } - }, [ - additionalActions, - buildFields, - children, - classes.actionBar, - formFactor, - formLabel, - formSubtitle, - formik, - isSubForm, - resetLabel, - submitLabel, - ]); + }; if (!isEmpty(fieldArray)) { return ( @@ -486,7 +513,7 @@ const FormFieldSet = ({ { - return buildFormFactor; + return buildFormFactor(arrayHelpers); }} /> @@ -494,7 +521,7 @@ const FormFieldSet = ({ } return ( - {buildFormFactor} + {buildFormFactor()} ); }; diff --git a/src/components/FormBuilder/index.stories.js b/src/components/FormBuilder/index.stories.js index 34cec98..ad2aa77 100644 --- a/src/components/FormBuilder/index.stories.js +++ b/src/components/FormBuilder/index.stories.js @@ -460,17 +460,12 @@ const NestedStory = ({ ...args }) => { ( - - - - - )} > {(subform ?? []).map((x, subidx) => { if (!x) { @@ -480,17 +475,12 @@ const NestedStory = ({ ...args }) => { ( - - - - )} + /> ); })}