@amxchange/grid-view-web-client
Version:
amxchange grid view framework web client in react ( a module extracted from existing jax )
147 lines (127 loc) • 4.83 kB
JSX
import React, { useImperativeHandle, useRef, useState } from "react";
import TextField from "./TextField";
import NumberField from "./NumberField";
import DisplayField from "./DisplayField";
import SelectField from "./SelectField";
import RadioInput from "./RadioInput";
import SwitchField from "./SwitchField";
import DateTimeField from "./DateTimeField";
import { validationService, getValidators } from "./constants";
import "../../assets/modules/_form-field.scss";
import DateField from "./DateField";
const formFields = {
text: TextField,
number: NumberField,
display: DisplayField,
select: SelectField,
radio: RadioInput,
switch: SwitchField,
date: DateField,
"date-time": DateTimeField
};
const FormField = React.forwardRef(
(
{
controlled = false,
type = "text",
id = `uniqId-${+new Date()}`,
value = "",
onChange,
disabled,
required,
validationProfiles, // registered common validation methods
validator, // custom validation method
inputValidations, // validate user input before setting it in state
liveValidations, // validate on every input update
...restProps
},
ref
) => {
// options that are to be passed ahead
let fieldOpts = {
type,
disabled,
...restProps
};
const inputRef = useRef();
const [_value, setValue] = useState("");
const [errorMsg, setErrorMsg] = useState("");
const focus = () => inputRef.current?.focus();
const getVal = () => (controlled ? value : _value);
const setVal = val => setValue(val);
const setError = msg => setErrorMsg(msg);
const clearError = () => setErrorMsg("");
const val = val => {
if (val === undefined) return getVal();
return setVal(val);
};
const isValid = () => {
if ((required === false && getVal() === "") || disabled) {
clearError();
return true;
}
let validators = [
...(validator ? [validator] : []),
...getValidators(validationProfiles ? ["default", ...validationProfiles] : ["default"])
];
let validationResults = validationService.validate(validators, {
value: getVal(),
config: fieldOpts
});
let errors = validationResults.filter(v => !v.valid);
if (errors.length) setError(errors[0].errorMsg);
return errorMsg ? false : errors.length === 0; /* In case error is set explicitly */
};
const isInputValid = value => {
let validators = getValidators(inputValidations);
let validationResults = validationService.validate(validators, {
value,
config: fieldOpts
});
return validationResults.every(v => v.valid === true);
};
const liveValidate = value => {
let liveValidators = getValidators(liveValidations || ["default"]);
let validationResults = validationService.validate(liveValidators, {
value,
config: fieldOpts
});
let errors = validationResults.filter(v => v.valid === false);
if (errors.length) setError(errors[0].errorMsg);
};
const onChangeInput = async (newVal, notFromUser) => {
if (inputValidations && !isInputValid(newVal)) return;
clearError();
if (controlled) {
if (liveValidations) liveValidate(newVal);
if (onChange) onChange(newVal);
return;
}
setVal(newVal);
if (liveValidations) liveValidate(newVal);
if (onChange && !notFromUser) onChange(newVal);
};
useImperativeHandle(ref, () => ({
focus,
isValid,
val,
setError,
clearError
}));
let Field = formFields[type];
if (!Field) {
Field = formFields["text"];
console.error(`FormField type : ${type} not found, falling back to 'text'`);
}
return (
<Field
ref={inputRef}
value={controlled ? value : _value}
onChangeInput={onChangeInput}
errorMsg={errorMsg} // later accomodate warning and default texts
{...fieldOpts}
/>
);
}
);
export default FormField;