react-formr
Advanced tools
Comparing version 1.3.1 to 1.3.2
import React from 'react'; | ||
import { FormrProps } from './Types'; | ||
declare const _default: React.NamedExoticComponent<FormrProps>; | ||
import { FormrWrapperProps } from './Types'; | ||
declare const _default: React.NamedExoticComponent<FormrWrapperProps>; | ||
export default _default; |
164
lib/formr.js
@@ -1,157 +0,19 @@ | ||
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]; | ||
var __rest = (this && this.__rest) || function (s, e) { | ||
var t = {}; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) | ||
t[p] = s[p]; | ||
if (s != null && typeof Object.getOwnPropertySymbols === "function") | ||
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { | ||
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) | ||
t[p[i]] = s[p[i]]; | ||
} | ||
return t; | ||
}; | ||
return __assign.apply(this, arguments); | ||
return t; | ||
}; | ||
import React, { useRef, useState, useCallback, useEffect } from 'react'; | ||
import { validator, fieldBools } from './utils'; | ||
import React from 'react'; | ||
import useFormr from './useFormr'; | ||
var Formr = function (_a) { | ||
var formFields = _a.formFields, children = _a.children, validation = _a.validation, _b = _a.disbaleAutoFocus, disbaleAutoFocus = _b === void 0 ? false : _b, _c = _a.onChange, onChange = _c === void 0 ? function () { } : _c, _d = _a.onFinishFocus, onFinishFocus = _d === void 0 ? function () { } : _d; | ||
// States & refs | ||
var _e = useState(formFields), values = _e[0], setValues = _e[1]; | ||
var _f = useState(fieldBools(formFields)), touched = _f[0], setTouched = _f[1]; | ||
var valid = useRef(fieldBools(validation || {})); | ||
var refs = useRef([]); | ||
// Additional listener for any change in form fields | ||
useEffect(function () { | ||
onChange(values); | ||
}, [values]); | ||
// Setting valid helper | ||
var setValid = useCallback(function (key, validated) { | ||
var _a; | ||
valid.current = __assign(__assign({}, valid.current), (_a = {}, _a[key] = validated, _a)); | ||
}, [valid]); | ||
// run validation & set validation | ||
var fieldValidation = function (key, value) { | ||
if (validation && validation[key]) { | ||
var validationObj = validation[key]; | ||
// if validation type is set | ||
if (validationObj.type) { | ||
var validation_1 = validator(validationObj.type, value); | ||
setValid(key, validation_1); | ||
} | ||
else if (validationObj.rules) { | ||
// if validation rules is set | ||
var validation_2 = validator('rules', value, validationObj.rules); | ||
setValid(key, validation_2); | ||
} | ||
else if (validationObj.required) { | ||
var validation_3 = value !== ''; | ||
setValid(key, validation_3); | ||
} | ||
else { | ||
// no validation | ||
setValid(key, true); | ||
} | ||
} | ||
}; | ||
// Input change listner | ||
var onChangeHandler = useCallback(function (key, value) { | ||
// Set form values | ||
setValues(function (prev) { | ||
var _a; | ||
return (__assign(__assign({}, prev), (_a = {}, _a[key] = value, _a))); | ||
}); | ||
fieldValidation(key, value); | ||
}, [setValues, values]); | ||
// Input Blur listner | ||
var onBlurHandler = useCallback(function (key) { | ||
setTouched(function (prev) { | ||
var _a; | ||
return (__assign(__assign({}, prev), (_a = {}, _a[key] = true, _a))); | ||
}); | ||
fieldValidation(key, values[key]); | ||
}, [setTouched, values]); | ||
// formSubmit listner | ||
var onSubmitHandler = useCallback(function (callback) { | ||
// run validation | ||
Object.keys(values).forEach(function (key) { | ||
fieldValidation(key, values[key]); | ||
}); | ||
var submissionAllowed = !Object.keys(formFields).some(function (key) { | ||
// console.log(valid.current[key]); | ||
// reurn true if any nonvalid formfields | ||
if (validation && | ||
validation[key] && | ||
validation[key].hasOwnProperty('required') && | ||
validation[key].required) { | ||
return valid.current[key] === false; | ||
} | ||
else { | ||
// if no validation or no required fields | ||
return false; | ||
} | ||
}); | ||
// console.log({ submissionAllowed }); | ||
if (submissionAllowed) { | ||
callback(values); | ||
return true; | ||
} | ||
else { | ||
// blurr all fields to show error if any | ||
Object.keys(touched).forEach(onBlurHandler); | ||
} | ||
return false; | ||
}, [values, touched, valid, onBlurHandler]); | ||
// Mapping ref object to formField keys | ||
var refsHandler = useCallback(function (key, ref) { | ||
refs.current[Object.keys(formFields).indexOf(key)] = ref; | ||
}, [formFields]); | ||
var onSubmitEditingHandler = useCallback(function (key) { | ||
if (disbaleAutoFocus) { | ||
return; | ||
} | ||
var cField = Object.keys(formFields).indexOf(key); | ||
var tFields = Object.keys(formFields).length; | ||
if (cField + 1 < tFields) { | ||
for (var idx = cField; idx <= tFields; idx++) { | ||
var focusable = refs.current[Object.keys(formFields).indexOf(key) + | ||
(idx - cField) + | ||
1]; | ||
if (focusable) { | ||
focusable.focus(); | ||
return; | ||
} | ||
} | ||
onFinishFocus(values); | ||
} | ||
else { | ||
onFinishFocus(values); | ||
} | ||
}, [formFields, onFinishFocus, values]); | ||
var inputBinder = useCallback(function (key) { | ||
return { | ||
onChangeText: function (text) { return onChangeHandler(key, text); }, | ||
onBlur: function () { return onBlurHandler(key); }, | ||
value: values[key], | ||
touched: touched[key], | ||
valid: valid.current[key], | ||
ref: function (ref) { return refsHandler(key, ref); }, | ||
onSubmitEditing: function () { return onSubmitEditingHandler(key); } | ||
}; | ||
}, [onChangeHandler, onBlurHandler, values, touched, valid, formFields]); | ||
var outputRefs = __assign({}, formFields); | ||
Object.keys(formFields).map(function (val, key) { | ||
outputRefs[val] = refs.current[key]; | ||
}); | ||
var returnItem = { | ||
onChangeHandler: onChangeHandler, | ||
onBlurHandler: onBlurHandler, | ||
onSubmitEditingHandler: onSubmitEditingHandler, | ||
onSubmitHandler: onSubmitHandler, | ||
inputBinder: inputBinder, | ||
refsHandler: refsHandler, | ||
refs: outputRefs, | ||
values: values, | ||
touched: touched, | ||
valid: valid.current | ||
}; | ||
var children = _a.children, props = __rest(_a, ["children"]); | ||
var returnItem = useFormr(props); | ||
return children(returnItem); | ||
}; | ||
export default React.memo(Formr); |
@@ -28,9 +28,11 @@ export interface FormMessages { | ||
export interface FormrProps { | ||
children: any; | ||
formFields: StringObject; | ||
validation?: FormrValidation; | ||
disbaleAutoFocus?: boolean; | ||
onChange?: (values: StringObject) => object; | ||
onChange?: (values: StringObject) => void; | ||
onFinishFocus?: (values: StringObject) => void; | ||
} | ||
export interface FormrWrapperProps extends FormrProps { | ||
children?: any; | ||
} | ||
export interface InputBinderProps { | ||
@@ -37,0 +39,0 @@ onChangeText: (text: string) => void; |
@@ -15,6 +15,6 @@ var __assign = (this && this.__assign) || function () { | ||
var useFormr = function (_a) { | ||
var formFields = _a.formFields, validation = _a.validation, disbaleAutoFocus = _a.disbaleAutoFocus, _b = _a.onFinishFocus, onFinishFocus = _b === void 0 ? function () { } : _b, _c = _a.onChange, onChange = _c === void 0 ? function () { } : _c; | ||
var formFields = _a.formFields, validation = _a.validation, _b = _a.disbaleAutoFocus, disbaleAutoFocus = _b === void 0 ? false : _b, _c = _a.onFinishFocus, onFinishFocus = _c === void 0 ? function () { } : _c, _d = _a.onChange, onChange = _d === void 0 ? function () { } : _d; | ||
// States & refs | ||
var _d = useState(formFields), values = _d[0], setValues = _d[1]; | ||
var _e = useState(fieldBools(formFields)), touched = _e[0], setTouched = _e[1]; | ||
var _e = useState(formFields), values = _e[0], setValues = _e[1]; | ||
var _f = useState(fieldBools(formFields)), touched = _f[0], setTouched = _f[1]; | ||
var valid = useRef(fieldBools(validation || {})); | ||
@@ -21,0 +21,0 @@ var refs = useRef([]); |
{ | ||
"name": "react-formr", | ||
"version": "1.3.1", | ||
"version": "1.3.2", | ||
"description": "Form managing component for React & React Native", | ||
@@ -5,0 +5,0 @@ "main": "./lib/index.js", |
104
README.md
@@ -1,2 +0,1 @@ | ||
![react-formr](https://raw.githubusercontent.com/ltsharma/react-formr/master/img/formr-banner.png) | ||
@@ -11,7 +10,6 @@ | ||
Centralised Solution for managing values, validations & input focusing in react native. | ||
Centralised Solution for managing values & validation in react native, the options are unlimited | ||
## Features | ||
# Features | ||
1. Form validation on given rules (regex) or predefined types(email, phone, etc). | ||
@@ -23,26 +21,89 @@ 2. Input binder function includes almost everything `TextInput` required to handle form. | ||
## Detailed blog post | ||
[Easy React Native Form management with react-formr](https://dev.to/ltsharma/easy-react-native-form-management-with-react-formr-47n5) | ||
**Detailed blog post** [Easy React Native Form management with react-formr](https://dev.to/ltsharma/easy-react-native-form-management-with-react-formr-47n5) | ||
# Installation | ||
## Installation | ||
Yarn \ | ||
`yarn add react-formr` \ | ||
NPM \ | ||
`npm i --save react-formr` | ||
**Yarn** | ||
# Example Usage | ||
```bash | ||
yarn add react-formr | ||
``` | ||
1. Import `Formr` | ||
**NPM** | ||
```bash | ||
npm i --save react-formr | ||
``` | ||
## Example Usage | ||
### Import | ||
import `Formr` to use with Formr wrapping component OR import `{useFormr}` to use Formr Hook. | ||
```javascript | ||
import Formr from 'react-formr'; | ||
import Formr, { useFormr } from 'react-formr'; | ||
``` | ||
2. Use it | ||
### Using `useFormr` Hook. | ||
```javascript | ||
export const App = () => { | ||
const { | ||
onChangeHandler, | ||
onBlurHandler, | ||
onSubmitEditingHandler, | ||
onSubmitHandler, | ||
inputBinder, | ||
refsHandler, | ||
values, | ||
touched, | ||
valid | ||
} = useFormr({ | ||
formFields: { email: '', phone: '' }, | ||
validation: { | ||
email: { required: true, type: 'email' }, | ||
phone: { type: 'phone' } | ||
} | ||
}); | ||
return ( | ||
<View> | ||
<TextInput | ||
style={{ | ||
borderBottomColor: 'black', | ||
borderWidth: 1, | ||
width: '100%' | ||
}} | ||
onChangeText={(e) => onChangeHandler('email', e)} | ||
onBlur={() => onBlurHandler('email')} | ||
value={values.email} | ||
ref={(ref) => refsHandler('password', ref)} | ||
/> | ||
{touched.email && !valid.email && <Text>Not valid</Text>} | ||
{/* Using input binder, No need to take any other function than inputBinder from formr to work with input*/} | ||
<TextInput | ||
style={{ | ||
borderBottomColor: 'black', | ||
borderWidth: 1, | ||
width: '100%' | ||
}} | ||
{...inputBinder('phone')} | ||
/> | ||
{touched.phone && !valid.phone && <Text>Not valid</Text>} | ||
<Button | ||
onPress={() => onSubmitHandler(console.log)} | ||
title="Submit" | ||
color="#841584" | ||
/> | ||
</View> | ||
); | ||
}; | ||
``` | ||
### Using `Formr` wrapping component. | ||
```javascript | ||
export const App = () => { | ||
return ( | ||
<View> | ||
<Formr | ||
@@ -81,3 +142,3 @@ formFields={{ email: '', phone: '' }} | ||
)} | ||
// Using input binder | ||
{/* Using input binder, No need to take any other function than inputBinder from formr to work with input*/} | ||
<TextInput | ||
@@ -94,3 +155,7 @@ style={{ | ||
)} | ||
<Button onPress={() => onSubmitHandler(console.log)} title="Submit" color="#841584" /> | ||
<Button | ||
onPress={() => onSubmitHandler(console.log)} | ||
title="Submit" | ||
color="#841584" | ||
/> | ||
</>; | ||
@@ -133,4 +198,5 @@ }} | ||
- [ ] To add more validation types | ||
- [ ] To remove validator dependancy | ||
- [ ] Add testing | ||
- [ ] To add more validation types / Yup | ||
- [ ] To remove validator dependancy / Yup | ||
- [ ] Other elements & values support |
191
src/formr.ts
import React, { useRef, useState, useCallback, useEffect } from 'react'; | ||
import { validator, fieldBools } from './utils'; | ||
import { | ||
BoolObject, | ||
FormValidation, | ||
FormrProps, | ||
FormrFunctions, | ||
StringObject, | ||
InputBinderProps | ||
} from './Types'; | ||
import { FormrWrapperProps } from './Types'; | ||
import useFormr from './useFormr'; | ||
const Formr: React.FC<FormrProps> = ({ | ||
formFields, | ||
children, | ||
validation, | ||
disbaleAutoFocus = false, | ||
onChange = () => {}, | ||
onFinishFocus = () => {} | ||
}) => { | ||
// States & refs | ||
const [values, setValues] = useState<StringObject>(formFields); | ||
const [touched, setTouched] = useState<BoolObject>(fieldBools(formFields)); | ||
const valid = useRef<BoolObject>(fieldBools(validation || {})); | ||
const refs = useRef<any>([]); | ||
// Additional listener for any change in form fields | ||
useEffect(() => { | ||
onChange(values); | ||
}, [values]); | ||
// Setting valid helper | ||
const setValid = useCallback( | ||
(key: string, validated: boolean) => { | ||
valid.current = { ...valid.current, [key]: validated }; | ||
}, | ||
[valid] | ||
); | ||
// run validation & set validation | ||
const fieldValidation = (key: string, value: string) => { | ||
if (validation && validation[key]) { | ||
const validationObj: FormValidation = validation[key]; | ||
// if validation type is set | ||
if (validationObj.type) { | ||
const validation = validator(validationObj.type, value); | ||
setValid(key, validation); | ||
} else if (validationObj.rules) { | ||
// if validation rules is set | ||
const validation = validator( | ||
'rules', | ||
value, | ||
validationObj.rules | ||
); | ||
setValid(key, validation); | ||
} else if (validationObj.required) { | ||
const validation = value !== ''; | ||
setValid(key, validation); | ||
} else { | ||
// no validation | ||
setValid(key, true); | ||
} | ||
} | ||
}; | ||
// Input change listner | ||
const onChangeHandler = useCallback<FormrFunctions['onChangeHandler']>( | ||
(key, value) => { | ||
// Set form values | ||
setValues((prev) => ({ ...prev, [key]: value })); | ||
fieldValidation(key, value); | ||
}, | ||
[setValues, values] | ||
); | ||
// Input Blur listner | ||
const onBlurHandler = useCallback<FormrFunctions['onBlurHandler']>( | ||
(key) => { | ||
setTouched((prev) => ({ ...prev, [key]: true })); | ||
fieldValidation(key, values[key]); | ||
}, | ||
[setTouched, values] | ||
); | ||
// formSubmit listner | ||
const onSubmitHandler = useCallback<FormrFunctions['onSubmitHandler']>( | ||
(callback) => { | ||
// run validation | ||
Object.keys(values).forEach((key) => { | ||
fieldValidation(key, values[key]); | ||
}); | ||
const submissionAllowed: boolean = !Object.keys(formFields).some( | ||
(key) => { | ||
// console.log(valid.current[key]); | ||
// reurn true if any nonvalid formfields | ||
if ( | ||
validation && | ||
validation[key] && | ||
validation[key].hasOwnProperty('required') && | ||
validation[key].required | ||
) { | ||
return valid.current[key] === false; | ||
} else { | ||
// if no validation or no required fields | ||
return false; | ||
} | ||
} | ||
); | ||
// console.log({ submissionAllowed }); | ||
if (submissionAllowed) { | ||
callback(values); | ||
return true; | ||
} else { | ||
// blurr all fields to show error if any | ||
Object.keys(touched).forEach(onBlurHandler); | ||
} | ||
return false; | ||
}, | ||
[values, touched, valid, onBlurHandler] | ||
); | ||
// Mapping ref object to formField keys | ||
const refsHandler = useCallback<FormrFunctions['refsHandler']>( | ||
(key, ref) => { | ||
refs.current[Object.keys(formFields).indexOf(key)] = ref; | ||
}, | ||
[formFields] | ||
); | ||
const onSubmitEditingHandler = useCallback< | ||
FormrFunctions['onSubmitEditingHandler'] | ||
>( | ||
(key) => { | ||
if (disbaleAutoFocus) { | ||
return; | ||
} | ||
const cField = Object.keys(formFields).indexOf(key); | ||
const tFields = Object.keys(formFields).length; | ||
if (cField + 1 < tFields) { | ||
for (let idx = cField; idx <= tFields; idx++) { | ||
const focusable = | ||
refs.current[ | ||
Object.keys(formFields).indexOf(key) + | ||
(idx - cField) + | ||
1 | ||
]; | ||
if (focusable) { | ||
focusable.focus(); | ||
return; | ||
} | ||
} | ||
onFinishFocus(values); | ||
} else { | ||
onFinishFocus(values); | ||
} | ||
}, | ||
[formFields, onFinishFocus, values] | ||
); | ||
const inputBinder = useCallback<FormrFunctions['inputBinder']>( | ||
(key) => { | ||
return { | ||
onChangeText: (text: string) => onChangeHandler(key, text), | ||
onBlur: () => onBlurHandler(key), | ||
value: values[key], | ||
touched: touched[key], | ||
valid: valid.current[key], | ||
ref: (ref: any) => refsHandler(key, ref), | ||
onSubmitEditing: () => onSubmitEditingHandler(key) | ||
}; | ||
}, | ||
[onChangeHandler, onBlurHandler, values, touched, valid, formFields] | ||
); | ||
const outputRefs = { ...formFields }; | ||
Object.keys(formFields).map((val, key) => { | ||
outputRefs[val] = refs.current[key]; | ||
}); | ||
const returnItem: FormrFunctions = { | ||
onChangeHandler, | ||
onBlurHandler, | ||
onSubmitEditingHandler, | ||
onSubmitHandler, | ||
inputBinder, | ||
refsHandler, | ||
refs: outputRefs, | ||
values, | ||
touched, | ||
valid: valid.current | ||
}; | ||
const Formr: React.FC<FormrWrapperProps> = ({ children, ...props }) => { | ||
const returnItem = useFormr(props); | ||
return children(returnItem); | ||
@@ -191,0 +8,0 @@ }; |
export interface FormMessages { | ||
empty?: string; | ||
error?: string; | ||
valid?: string; | ||
empty?: string; | ||
error?: string; | ||
valid?: string; | ||
} | ||
export interface FormValidation { | ||
type?: string; | ||
rules?: string; | ||
required?: boolean; | ||
messages?: FormMessages; | ||
type?: string; | ||
rules?: string; | ||
required?: boolean; | ||
messages?: FormMessages; | ||
} | ||
export interface BoolObject { | ||
[key: string]: boolean; | ||
[key: string]: boolean; | ||
} | ||
export interface NullObject { | ||
[key: string]: null; | ||
[key: string]: null; | ||
} | ||
export interface StringObject { | ||
[key: string]: string; | ||
[key: string]: string; | ||
} | ||
export interface AnyObject { | ||
[key: string]: any; | ||
[key: string]: any; | ||
} | ||
export interface FormrValidation { | ||
[key: string]: FormValidation; | ||
[key: string]: FormValidation; | ||
} | ||
export interface FormrProps { | ||
children: any; | ||
formFields: StringObject; | ||
validation?: FormrValidation; | ||
disbaleAutoFocus?: boolean; | ||
onChange?: (values: StringObject) => object; | ||
onFinishFocus?: (values: StringObject) => void; | ||
formFields: StringObject; | ||
validation?: FormrValidation; | ||
disbaleAutoFocus?: boolean; | ||
onChange?: (values: StringObject) => void; | ||
onFinishFocus?: (values: StringObject) => void; | ||
} | ||
export interface FormrWrapperProps extends FormrProps { | ||
children?: any; | ||
} | ||
export interface InputBinderProps { | ||
onChangeText: (text: string) => void; | ||
onBlur: () => void; | ||
onSubmitEditing: () => void; | ||
value: string; | ||
valid: boolean; | ||
touched: boolean; | ||
ref: any; | ||
onChangeText: (text: string) => void; | ||
onBlur: () => void; | ||
onSubmitEditing: () => void; | ||
value: string; | ||
valid: boolean; | ||
touched: boolean; | ||
ref: any; | ||
} | ||
export interface FormrFunctions { | ||
onChangeHandler: (key: string, value: any) => void; | ||
onBlurHandler: (key: string) => void; | ||
onSubmitEditingHandler: (key: string) => void; | ||
onSubmitHandler: (callback: (values: StringObject) => void) => boolean; | ||
inputBinder: (key: string) => InputBinderProps; | ||
refsHandler: (key: string, ref: any) => void; | ||
refs: AnyObject; | ||
values: StringObject; | ||
touched: BoolObject; | ||
valid: BoolObject; | ||
onChangeHandler: (key: string, value: any) => void; | ||
onBlurHandler: (key: string) => void; | ||
onSubmitEditingHandler: (key: string) => void; | ||
onSubmitHandler: (callback: (values: StringObject) => void) => boolean; | ||
inputBinder: (key: string) => InputBinderProps; | ||
refsHandler: (key: string, ref: any) => void; | ||
refs: AnyObject; | ||
values: StringObject; | ||
touched: BoolObject; | ||
valid: BoolObject; | ||
} |
@@ -1,3 +0,15 @@ | ||
import React,{useState,useRef,useEffect,useCallback, useLayoutEffect} from 'react'; | ||
import { BoolObject, FormrFunctions, FormrProps, FormValidation, StringObject } from './Types'; | ||
import React, { | ||
useState, | ||
useRef, | ||
useEffect, | ||
useCallback, | ||
useLayoutEffect | ||
} from 'react'; | ||
import { | ||
BoolObject, | ||
FormrFunctions, | ||
FormrProps, | ||
FormValidation, | ||
StringObject | ||
} from './Types'; | ||
import { fieldBools, validator } from './utils'; | ||
@@ -8,179 +20,178 @@ | ||
validation, | ||
disbaleAutoFocus, | ||
onFinishFocus=()=>{} | ||
onChange=()=>{} | ||
}:FormrProps):FormrFunctions =>{ | ||
disbaleAutoFocus = false, | ||
onFinishFocus = () => {}, | ||
onChange = () => {} | ||
}: FormrProps): FormrFunctions => { | ||
// States & refs | ||
const [values, setValues] = useState<StringObject>(formFields); | ||
const [touched, setTouched] = useState<BoolObject>(fieldBools(formFields)); | ||
const valid = useRef<BoolObject>(fieldBools(validation || {})); | ||
const refs = useRef<any>([]); | ||
// States & refs | ||
const [values, setValues] = useState<StringObject>(formFields); | ||
const [touched, setTouched] = useState<BoolObject>(fieldBools(formFields)); | ||
const valid = useRef<BoolObject>(fieldBools(validation || {})); | ||
const refs = useRef<any>([]); | ||
// Additional listener for any change in form fields | ||
useEffect(() => { | ||
onChange(values); | ||
}, [values]); | ||
// Setting valid helper | ||
const setValid = useCallback( | ||
(key: string, validated: boolean) => { | ||
valid.current = { ...valid.current, [key]: validated }; | ||
}, | ||
[valid] | ||
); | ||
// run validation & set validation | ||
const fieldValidation = (key: string, value: string) => { | ||
if (validation && validation[key]) { | ||
const validationObj: FormValidation = validation[key]; | ||
// if validation type is set | ||
if (validationObj.type) { | ||
const validation = validator(validationObj.type, value); | ||
setValid(key, validation); | ||
} else if (validationObj.rules) { | ||
// if validation rules is set | ||
const validation = validator( | ||
'rules', | ||
value, | ||
validationObj.rules | ||
); | ||
setValid(key, validation); | ||
} else if (validationObj.required) { | ||
const validation = value !== ''; | ||
setValid(key, validation); | ||
} else { | ||
// no validation | ||
setValid(key, true); | ||
} | ||
} | ||
}; | ||
// Input change listner | ||
const onChangeHandler = useCallback<FormrFunctions['onChangeHandler']>( | ||
(key, value) => { | ||
// Set form values | ||
setValues((prev) => ({ ...prev, [key]: value })); | ||
fieldValidation(key, value); | ||
}, | ||
[setValues, values] | ||
); | ||
// Input Blur listner | ||
const onBlurHandler = useCallback<FormrFunctions['onBlurHandler']>( | ||
(key) => { | ||
setTouched((prev) => ({ ...prev, [key]: true })); | ||
fieldValidation(key, values[key]); | ||
}, | ||
[setTouched, values] | ||
); | ||
// formSubmit listner | ||
const onSubmitHandler = useCallback<FormrFunctions['onSubmitHandler']>( | ||
(callback) => { | ||
// run validation | ||
Object.keys(values).forEach((key) => { | ||
fieldValidation(key, values[key]); | ||
}); | ||
const submissionAllowed: boolean = !Object.keys(formFields).some( | ||
(key) => { | ||
// reurn true if any nonvalid formfields | ||
if ( | ||
validation && | ||
validation[key] && | ||
validation[key].hasOwnProperty('required') && | ||
validation[key].required | ||
) { | ||
return valid.current[key] === false; | ||
} else { | ||
// if no validation or no required fields | ||
return false; | ||
} | ||
} | ||
); | ||
if (submissionAllowed) { | ||
callback(values); | ||
return true; | ||
} else { | ||
// blurr all fields to show error if any | ||
Object.keys(touched).forEach(onBlurHandler); | ||
} | ||
return false; | ||
}, | ||
[values, touched, valid, onBlurHandler] | ||
); | ||
// Mapping ref object to formField keys | ||
const refsHandler = useCallback<FormrFunctions['refsHandler']>( | ||
(key, ref) => { | ||
refs.current[Object.keys(formFields).indexOf(key)] = ref; | ||
}, | ||
[formFields] | ||
); | ||
const onSubmitEditingHandler = useCallback< | ||
FormrFunctions['onSubmitEditingHandler'] | ||
>( | ||
(key) => { | ||
if (disbaleAutoFocus) { | ||
return; | ||
} | ||
const cField = Object.keys(formFields).indexOf(key); | ||
const tFields = Object.keys(formFields).length; | ||
if (cField + 1 < tFields) { | ||
for (let idx = cField; idx <= tFields; idx++) { | ||
const focusable = | ||
refs.current[ | ||
Object.keys(formFields).indexOf(key) + | ||
(idx - cField) + | ||
1 | ||
]; | ||
if (focusable) { | ||
focusable.focus(); | ||
return; | ||
} | ||
} | ||
onFinishFocus(values); | ||
} else { | ||
onFinishFocus(values); | ||
} | ||
}, | ||
[formFields, onFinishFocus, values] | ||
); | ||
const inputBinder = useCallback<FormrFunctions['inputBinder']>( | ||
(key) => { | ||
return { | ||
onChangeText: (text: string) => onChangeHandler(key, text), | ||
onBlur: () => onBlurHandler(key), | ||
value: values[key], | ||
touched: touched[key], | ||
valid: valid.current[key], | ||
ref: (ref: any) => refsHandler(key, ref), | ||
onSubmitEditing: () => onSubmitEditingHandler(key) | ||
}; | ||
}, | ||
[onChangeHandler, onBlurHandler, values, touched, valid, formFields] | ||
); | ||
const outputRefs = { ...formFields }; | ||
Object.keys(formFields).map((val, key) => { | ||
outputRefs[val] = refs.current[key]; | ||
}); | ||
const returnItem: FormrFunctions = { | ||
onChangeHandler, | ||
onBlurHandler, | ||
onSubmitEditingHandler, | ||
onSubmitHandler, | ||
inputBinder, | ||
refsHandler, | ||
refs: outputRefs, | ||
values, | ||
touched, | ||
valid: valid.current | ||
}; | ||
// Additional listener for any change in form fields | ||
useEffect(() => { | ||
onChange(values); | ||
}, [values]); | ||
return returnItem | ||
} | ||
// Setting valid helper | ||
const setValid = useCallback( | ||
(key: string, validated: boolean) => { | ||
valid.current = { ...valid.current, [key]: validated }; | ||
}, | ||
[valid] | ||
); | ||
export default useFormr; | ||
// run validation & set validation | ||
const fieldValidation = (key: string, value: string) => { | ||
if (validation && validation[key]) { | ||
const validationObj: FormValidation = validation[key]; | ||
// if validation type is set | ||
if (validationObj.type) { | ||
const validation = validator(validationObj.type, value); | ||
setValid(key, validation); | ||
} else if (validationObj.rules) { | ||
// if validation rules is set | ||
const validation = validator( | ||
'rules', | ||
value, | ||
validationObj.rules | ||
); | ||
setValid(key, validation); | ||
} else if (validationObj.required) { | ||
const validation = value !== ''; | ||
setValid(key, validation); | ||
} else { | ||
// no validation | ||
setValid(key, true); | ||
} | ||
} | ||
}; | ||
// Input change listner | ||
const onChangeHandler = useCallback<FormrFunctions['onChangeHandler']>( | ||
(key, value) => { | ||
// Set form values | ||
setValues((prev) => ({ ...prev, [key]: value })); | ||
fieldValidation(key, value); | ||
}, | ||
[setValues, values] | ||
); | ||
// Input Blur listner | ||
const onBlurHandler = useCallback<FormrFunctions['onBlurHandler']>( | ||
(key) => { | ||
setTouched((prev) => ({ ...prev, [key]: true })); | ||
fieldValidation(key, values[key]); | ||
}, | ||
[setTouched, values] | ||
); | ||
// formSubmit listner | ||
const onSubmitHandler = useCallback<FormrFunctions['onSubmitHandler']>( | ||
(callback) => { | ||
// run validation | ||
Object.keys(values).forEach((key) => { | ||
fieldValidation(key, values[key]); | ||
}); | ||
const submissionAllowed: boolean = !Object.keys(formFields).some( | ||
(key) => { | ||
// reurn true if any nonvalid formfields | ||
if ( | ||
validation && | ||
validation[key] && | ||
validation[key].hasOwnProperty('required') && | ||
validation[key].required | ||
) { | ||
return valid.current[key] === false; | ||
} else { | ||
// if no validation or no required fields | ||
return false; | ||
} | ||
} | ||
); | ||
if (submissionAllowed) { | ||
callback(values); | ||
return true; | ||
} else { | ||
// blurr all fields to show error if any | ||
Object.keys(touched).forEach(onBlurHandler); | ||
} | ||
return false; | ||
}, | ||
[values, touched, valid, onBlurHandler] | ||
); | ||
// Mapping ref object to formField keys | ||
const refsHandler = useCallback<FormrFunctions['refsHandler']>( | ||
(key, ref) => { | ||
refs.current[Object.keys(formFields).indexOf(key)] = ref; | ||
}, | ||
[formFields] | ||
); | ||
const onSubmitEditingHandler = useCallback< | ||
FormrFunctions['onSubmitEditingHandler'] | ||
>( | ||
(key) => { | ||
if (disbaleAutoFocus) { | ||
return; | ||
} | ||
const cField = Object.keys(formFields).indexOf(key); | ||
const tFields = Object.keys(formFields).length; | ||
if (cField + 1 < tFields) { | ||
for (let idx = cField; idx <= tFields; idx++) { | ||
const focusable = | ||
refs.current[ | ||
Object.keys(formFields).indexOf(key) + | ||
(idx - cField) + | ||
1 | ||
]; | ||
if (focusable) { | ||
focusable.focus(); | ||
return; | ||
} | ||
} | ||
onFinishFocus(values); | ||
} else { | ||
onFinishFocus(values); | ||
} | ||
}, | ||
[formFields, onFinishFocus, values] | ||
); | ||
const inputBinder = useCallback<FormrFunctions['inputBinder']>( | ||
(key) => { | ||
return { | ||
onChangeText: (text: string) => onChangeHandler(key, text), | ||
onBlur: () => onBlurHandler(key), | ||
value: values[key], | ||
touched: touched[key], | ||
valid: valid.current[key], | ||
ref: (ref: any) => refsHandler(key, ref), | ||
onSubmitEditing: () => onSubmitEditingHandler(key) | ||
}; | ||
}, | ||
[onChangeHandler, onBlurHandler, values, touched, valid, formFields] | ||
); | ||
const outputRefs = { ...formFields }; | ||
Object.keys(formFields).map((val, key) => { | ||
outputRefs[val] = refs.current[key]; | ||
}); | ||
const returnItem: FormrFunctions = { | ||
onChangeHandler, | ||
onBlurHandler, | ||
onSubmitEditingHandler, | ||
onSubmitHandler, | ||
inputBinder, | ||
refsHandler, | ||
refs: outputRefs, | ||
values, | ||
touched, | ||
valid: valid.current | ||
}; | ||
return returnItem; | ||
}; | ||
export default useFormr; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
198
94217
826