src/errors.js (74 lines of code) (raw):
import {getIn} from 'formik';
import {iterateFields} from './utils';
import renderTextNode from './renderTextNode';
import {getComputedProperties} from './rules';
export const getFieldErrors = (path, internal, external) => {
let internalErrors = getIn(internal, path) || [];
let externalErrors = getIn(external, path) || [];
if (typeof internalErrors === 'string') {
internalErrors = [internalErrors];
}
if (typeof externalErrors === 'string') {
externalErrors = [externalErrors];
}
return [
...externalErrors,
...internalErrors,
];
};
const getErrorSummaryFieldLabel = (fieldConfig, context) => {
if (fieldConfig.errorSummaryLabel) {
return fieldConfig.errorSummaryLabel;
}
// Attempt to use the field's 'label', this is just a convention.
if (fieldConfig.data && fieldConfig.data.label) {
return renderTextNode(fieldConfig.data.label, 'span', context);
}
return '';
};
export const getErrorSummaryData = (config, internalErrors, externalErrors, computedProperties) => {
const errorSummaryData = [];
for (const {treePath, fieldConfig} of iterateFields(config)) {
let fieldErrors = null;
const fieldComputedProperties = getComputedProperties(computedProperties, treePath);
if (fieldConfig.path && fieldComputedProperties.shown) {
fieldErrors = getFieldErrors(fieldConfig.path, internalErrors, externalErrors);
}
if (fieldErrors && fieldErrors.length) {
errorSummaryData.push({
fieldId: `${config.id}.${treePath}`,
label: getErrorSummaryFieldLabel(fieldConfig, config.context),
errors: fieldErrors,
});
}
}
return errorSummaryData;
};
const getFieldErrorToDisplay = (errors, externalErrors, touched) => {
if (externalErrors && externalErrors.length) {
return externalErrors[0];
}
if (touched && errors && errors.length) {
return errors[0];
}
return undefined;
};
export const renderFieldError = (errors, externalErrors, touched) => {
const error = getFieldErrorToDisplay(errors, externalErrors, touched);
if (error && typeof error === 'string') {
return error;
}
if (error && error.message) {
return error.message;
}
return undefined;
};
export const renderChildError = (childName, errors, externalErrors, touched) => {
const error = getFieldErrorToDisplay(errors, externalErrors, touched);
let childError;
if (error && error.children && error.children.length) {
childError = error.children.find(child => {
return child.name === childName;
});
}
return childError ? childError.message : undefined;
};