envoc-form
Version:
Envoc form components
148 lines (147 loc) • 8.21 kB
JavaScript
;
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
var jsx_runtime_1 = require("react/jsx-runtime");
var react_1 = require("react");
var classnames_1 = __importDefault(require("classnames"));
var formik_1 = require("formik");
var FocusError_1 = __importDefault(require("./FocusError"));
var FormBasedPreventNavigation_1 = __importDefault(require("./FormBasedPreventNavigation"));
var ServerErrorContext_1 = require("./ServerErrorContext");
var Field_1 = __importDefault(require("../Field/Field"));
var FieldArray_1 = __importDefault(require("../FieldArray/FieldArray"));
var FormDefaults_1 = require("../FormDefaults");
var objectContainsNonSerializableProperty_1 = __importDefault(require("../utils/objectContainsNonSerializableProperty"));
var objectToFormData_1 = __importDefault(require("../utils/objectToFormData"));
/** Define a form. Uses [formik](https://formik.org/docs/overview). Usually contains many `<Field/>` components. */
function Form(_a) {
var children = _a.children, className = _a.className, style = _a.style, ignoreLostChanges = _a.ignoreLostChanges, onSubmit = _a.onSubmit, onFormDataSubmit = _a.onFormDataSubmit, initialValues = _a.initialValues, props = __rest(_a, ["children", "className", "style", "ignoreLostChanges", "onSubmit", "onFormDataSubmit", "initialValues"]);
// formik resets all error on each blur (with our settings)
// this means that ALL errors from the server disappear when any one field is blurred
// So, we have to store server errors ourselves
// Since we only use useStandardFormInput, that means there is only one consumer
var _b = (0, react_1.useState)({}), serverErrors = _b[0], setServerErrors = _b[1];
var serverErrorContextValue = (0, react_1.useMemo)(function () { return ({
errors: serverErrors,
getError: function (path) {
var lowered = path.toLowerCase();
return serverErrors && serverErrors[lowered];
},
setError: function (path, errorMessage) {
var _a;
var lowered = path.toLowerCase();
setServerErrors(Object.assign({}, serverErrors, (_a = {},
_a[lowered] = !errorMessage ? undefined : errorMessage,
_a)));
},
}); }, [serverErrors]);
return ((0, jsx_runtime_1.jsx)(formik_1.Formik, __assign({ validateOnChange: false, validateOnBlur: true, validateOnMount: false, initialValues: initialValues || {}, onSubmit: handleSubmit }, props, { children: (0, jsx_runtime_1.jsx)(ServerErrorContext_1.ServerErrorContext.Provider, __assign({ value: serverErrorContextValue }, { children: (0, jsx_runtime_1.jsxs)(formik_1.Form, __assign({ className: (0, classnames_1.default)(className, FormDefaults_1.FormDefaults.cssClassPrefix + 'form'), style: style }, { children: [(0, jsx_runtime_1.jsx)(FocusError_1.default, { serverErrors: serverErrorContextValue }), (0, jsx_runtime_1.jsx)(FormBasedPreventNavigation_1.default, { ignoreLostChanges: ignoreLostChanges }), children({
// hack for ref forwarding
Field: Field_1.default,
FieldArray: FieldArray_1.default,
})] })) })) })));
function handleSubmit(values, formikBag) {
var formData = undefined;
var submitFunc;
if ((0, objectContainsNonSerializableProperty_1.default)(values)) {
formData = (0, objectToFormData_1.default)(values, {
indices: true,
dotNotation: true,
allowEmptyArrays: true,
noFileListBrackets: true,
});
if (onFormDataSubmit === undefined) {
throw new Error('No onFormDataSubmit supplied for non-serializable properties.');
}
submitFunc = function () {
return onFormDataSubmit(formData !== null && formData !== void 0 ? formData : new FormData(), formikBag);
};
}
else {
if (onSubmit === undefined) {
formData = (0, objectToFormData_1.default)(values, {
indices: true,
dotNotation: true,
allowEmptyArrays: true,
noFileListBrackets: true,
});
if (onFormDataSubmit === undefined) {
// This error should never occur, as this case is covered by RequireAtLeastOne type safety
throw new Error('No onFormDataSubmit supplied for non-serializable properties.');
}
submitFunc = function () {
return onFormDataSubmit(formData !== null && formData !== void 0 ? formData : new FormData(), formikBag);
};
}
else {
submitFunc = function () { return onSubmit(values, formikBag); };
}
}
return submitFunc()
.then(function (response) {
return response;
})
.catch(function (err) {
//this is an http error
if (err &&
err.response &&
err.response.data &&
err.response.data.validationFailures) {
try {
var serverErrors_1 = err.response.data.validationFailures.reduce(function (acc, value) {
var _a;
// for simplicity, just keep it to one server error at a time per path
// don't care of the property name case changes
var path = (_a = value.propertyName) === null || _a === void 0 ? void 0 : _a.toLowerCase();
if (!!path && !!value.errorMessage) {
acc[path] = value.errorMessage;
}
return acc;
}, {});
setServerErrors(serverErrors_1);
}
catch (err) {
console.error('Failure to getErrorObject');
console.error(err);
throw err;
}
}
throw err;
});
}
}
exports.default = Form;
Form.DisplayFormState = DisplayFormState;
function DisplayFormState() {
var formState = (0, formik_1.useFormikContext)();
var serverErrorContext = (0, react_1.useContext)(ServerErrorContext_1.ServerErrorContext);
return ((0, jsx_runtime_1.jsx)("div", __assign({ style: { margin: '1rem 0' } }, { children: (0, jsx_runtime_1.jsxs)("pre", __assign({ style: {
background: '#f6f8fa',
fontSize: '.65rem',
padding: '.5rem',
} }, { children: [serverErrorContext && serverErrorContext.errors && ((0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("strong", { children: "serverErrors = " }), JSON.stringify(serverErrorContext.errors, null, 2)] })), (0, jsx_runtime_1.jsx)("strong", { children: "formState = " }), JSON.stringify(formState, null, 2)] })) })));
}