UNPKG

@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
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;