envoc-form
Version:
Envoc form components
93 lines (92 loc) • 4.47 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);
};
import { useContext, useEffect } from 'react';
import { useField, useFormikContext } from 'formik';
import { FieldNameContext } from './FieldNameContext';
import { ServerErrorContext } from '../Form/ServerErrorContext';
/** Provides a consistent way to deal with all form fields (non array). */
export default 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 = useContext(ServerErrorContext), getServerError = _b.getError, setServerError = _b.setError;
// ensure that form section values are obeyed, e.g. homeAddress.zipCode
var fieldNameContextValue = useContext(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 = useField({
name: name,
id: id ? id : name,
disabled: disabled,
validate: callAllValidators,
}), formikInput = _c[0], formikMeta = _c[1];
var _d = useFormikContext(), setFieldTouched = _d.setFieldTouched, setFieldValue = _d.setFieldValue, isSubmitting = _d.isSubmitting;
var touched = formikMeta.touched !== false && formikMeta.touched !== undefined;
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;
}
}
}
}