UNPKG

@s-chat/form-manager

Version:
150 lines 5.49 kB
// External import { useContext, useState, useRef, useMemo, useEffect } from 'react'; import { Validator } from 'livr'; import extraRules from 'livr-extra-rules'; // Internal import { FormManagerContext } from '../context/FormManager'; export const useFormManager = (fields, hookOptions = {}) => { const formManagerCTX = useContext(FormManagerContext); const options = { ...formManagerCTX.options, ...hookOptions }; Validator.defaultAutoTrim(true); Validator.registerDefaultRules(extraRules); Validator.registerDefaultRules(formManagerCTX.customValidationRules); const [timeStamp, setTimeStamp] = useState(Date.now()); const formFieldsData = Object.keys(fields).map((fieldName) => { const key = fieldName; const field = fields[key]; const originalType = field.type; const valueRef = useRef(field.defaultValue); const [value, setValue] = useState(field.defaultValue); const [type, setType] = useState(field.type); const [errorMessage, setErrorMessage] = useState(''); const isError = useMemo(() => !!errorMessage.length, [errorMessage]); const onChange = (...props) => { const valueSelector = (formManagerCTX.fieldValueSelector || {})[originalType] || (formManagerCTX.fieldValueSelector || {}).default; const newValue = valueSelector(...props); if (field.onBeforeChange) { field.onBeforeChange(newValue); } setValue(newValue); valueRef.current = newValue; if (field.onAfterChange) { field.onAfterChange(newValue); } }; useEffect(() => { setErrorMessage(''); if (options.isValidateOnChange) { validateForm(); } setTimeStamp(Date.now()); }, [value, type]); return { field, name: key, label: field.label, value, valueRef, isError, errorMessage, setValue, setType, setErrorMessage, originalType, bind: { name: key, id: key, type, onChange, ...field.htmlAttr, }, }; }); const getFieldType = (field, fields) => { if (!field.field.showIf) { return field.originalType; } const result = Object.keys(field.field.showIf).some(showIfKey => { const searchedField = fields.find(field => field.name === showIfKey); const fieldConditionValues = (field.field.showIf || {})[showIfKey]; if (!searchedField) { return false; } if (Array.isArray(fieldConditionValues)) { return fieldConditionValues.includes(`${searchedField.valueRef.current}`); } return `${searchedField.valueRef.current}` === fieldConditionValues; }); return !result ? 'hidden' : field.originalType; }; const formFieldObject = formFieldsData.reduce((acc, field) => { // @ts-ignore acc[field.name] = field.valueRef.current; return acc; }, {}); const validateForm = () => { const validatorData = formFieldsData .reduce((acc, fieldData) => { if (fieldData.bind.type === 'hidden') { return acc; } acc.rules[fieldData.name] = fieldData.field.validationRules; // @ts-ignore acc.data[fieldData.name] = fieldData.value; return acc; }, { rules: {}, data: {}, }); const validator = new Validator(validatorData.rules); const validData = validator.validate(validatorData.data); const errors = validator.getErrors(); formFieldsData.forEach((field) => { field.setErrorMessage(''); }); if (!errors) { setTimeStamp(Date.now()); return { ...validatorData.data, ...validData, }; } formFieldsData.forEach((field) => { if (!errors[field.name]) { return; } field.setErrorMessage(field.field.errorMessages && field.field.errorMessages[errors[field.name]] || (formManagerCTX.errorMessages || {})[errors[field.name]] || (formManagerCTX.errorMessages || {}).default); }); setTimeStamp(Date.now()); return; }; const bulkUpdateForm = (updateData) => { formFieldsData.forEach((field) => { if (typeof updateData[field.name] !== 'undefined') { field.setValue(updateData[field.name]); field.valueRef.current = updateData[field.name]; } }); }; const resetForm = () => { formFieldsData.forEach((field) => { field.setValue(field.field.defaultValue); field.setErrorMessage(''); }); }; return { fields: useMemo(() => { return formFieldsData.map((field, _, array) => { field.setType(getFieldType(field, array)); return field; }); }, [timeStamp]), formFieldObject, validateForm, resetForm, bulkUpdateForm, }; }; //# sourceMappingURL=useFormManager.js.map