envoc-form
Version:
Envoc form components
96 lines (95 loc) • 4.64 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);
};
Object.defineProperty(exports, "__esModule", { value: true });
var react_1 = require("react");
var formik_1 = require("formik");
var FieldNameContext_1 = require("./FieldNameContext");
var ServerErrorContext_1 = require("../Form/ServerErrorContext");
/** Provides a consistent way to deal with all form fields (non array). */
function useStandardField(_a) {
var providedId = _a.id, providedName = _a.name, disabled = _a.disabled, validate = _a.validate, normalize = _a.normalize;
// because the formik errors are evaluated all at the same time we need to keep server errors separate
var _b = (0, react_1.useContext)(ServerErrorContext_1.ServerErrorContext), getServerError = _b.getError, setServerError = _b.setError;
// ensure that form section values are obeyed, e.g. homeAddress.zipCode
var fieldNameContextValue = (0, react_1.useContext)(FieldNameContext_1.FieldNameContext);
var name = fieldNameContextValue
? "".concat(fieldNameContextValue, ".").concat(providedName)
: providedName;
// ensure that nested contexts don't have duplicate id issues when an id is specified
var id = providedId
? fieldNameContextValue
? "".concat(fieldNameContextValue, ".").concat(providedId)
: providedId
: name;
// ensure that our custom validation rules are handled
// e.g. we allow arrays of validators
var _c = (0, formik_1.useField)({
name: name,
id: id ? id : name,
disabled: disabled,
validate: callAllValidators,
}), formikInput = _c[0], formikMeta = _c[1];
var _d = (0, formik_1.useFormikContext)(), setFieldTouched = _d.setFieldTouched, setFieldValue = _d.setFieldValue, isSubmitting = _d.isSubmitting;
var touched = formikMeta.touched !== false && formikMeta.touched !== undefined;
(0, react_1.useEffect)(function () {
if (!touched && isSubmitting) {
// because we do not always register all fields up front.
// e.g. formik expects even a 'create' form to have all fields given, at least, blank values
// It looks like this was going to be a thing: https://github.com/jaredpalmer/formik/issues/691
// Formik appears to not have an active maintainer: https://github.com/jaredpalmer/formik/discussions/3526
// We previously had a different fix in place using handleBlur, but it was causing an infinite update cycle.
// This was noted as existing, but there was a note about it not working for FieldArray (this does appear to work in my testing with FieldArray)
setFieldTouched(name);
}
}, [isSubmitting, name, setFieldTouched, touched]);
// these are the props we expect consumers of this hook to pass directly to the input (or other control)
var resultInput = {
name: formikInput.name,
// pass any direct from server props through normalize without making the form dirty (e.g. phone number)
value: normalize ? normalize(formikInput.value) : formikInput.value,
onChange: handleChange,
onBlur: handleBlur,
// extensions to formik
id: id,
};
var resultMeta = __assign(__assign({}, formikMeta), { error: getServerError(name) || (touched ? formikMeta.error : undefined),
// extensions to formik
warning: undefined, touched: touched });
return [resultInput, resultMeta];
function handleBlur() {
formikInput.onBlur({ target: { name: name } });
}
function handleChange(value) {
if (disabled) {
return;
}
var normalized = normalize ? normalize(value) : value;
setFieldValue(name, normalized);
setServerError(name, undefined);
}
function callAllValidators(value) {
if (disabled || !validate) {
return;
}
if (!Array.isArray(validate)) {
return validate(value);
}
for (var i = 0; i < validate.length; i++) {
var result = validate[i](value);
if (result) {
return result;
}
}
}
}
exports.default = useStandardField;