Issue
I am evaluating react-hook-form for my application.
I am trying to find out a way to send dynamic values to custom validation function in react-hook-form.
We are using a library which in turn uses MUI, hence we have to use Controller component from react-hook-form.
I want to create a common validation rules file with common functions which I will be using in multiple forms. To achieve that I need to pass some values to the functions defined in validate option.
For instance for minMaxRule validation I need to define a common function which will accept min and max as parameters. I can see the types file of react-hook-form for validate will have a callback only with the value of that field. Is there any other way to achieve this ?
Form Component
import React, { BaseSyntheticEvent } from 'react';
import { Controller, useForm } from 'react-hook-form';
import { ruleSet } from '../../utils/validation/rules';
import { Validate, FieldValues } from 'react-hook-form';
export const ReactHookFormSample = (): JSX.Element => {
const { handleSubmit, control, formState: { errors }, getValues, register } = useForm({
mode: "onChange"
});
/**
* Call back on successful submit of form with form values
* @param data
* @param e
*/
const onSubmit = (data: any, e: BaseSyntheticEvent) => {
console.log('hook form', data);
}
/**
* Callback when form is submitted with errors
* @param errors
* @param e
*/
const onError = (errors: any, e: BaseSyntheticEvent) => {
console.log('When errors form', errors);
}
const getError = (field: FieldValues) => {
let errorStr = '';
let inputName = field?.name;
if (errors && errors?.[inputName]) {
errorStr = errors?.[inputName]?.message;
}
return errorStr;
}
return (
<>
<h3>Sample React hook form</h3>
<form onSubmit={handleSubmit(onSubmit, onError)}>
<Controller
name="user_name"
control={control}
rules={{ validate: {isRequired: ruleSet.isRequired, minLen: ruleSet.minLen, maxLen: ruleSet.maxLen } }}
render={({ field, fieldState: {error}, formState }) =>
<MyTextField placeholder="Enter user name here" error={!!error} {...field} />
}
/>
<br/>
<Controller
name="password"
control={control}
rules={{ validate: {isRequired: ruleSet.isRequired, minLen: ruleSet.minLen, maxLen: ruleSet.maxLen } }}
render={({ field, fieldState: {error}, formState }) =>
<MyTextField placeholder="Enter password here" error={!!error} {...field} />
}
/>
<br/>
<Controller
name="retype_password"
control={control}
rules={{ validate: {isRequired: ruleSet.isRequired, minMaxLen: ruleSet.minMaxLen, ruleSet.isValueEqual } }}
render={({ field, fieldState: {error}, formState }) =>
<MyTextField placeholder="Retype password here" error={!!error} {...field} />
}
/>
<br/>
<MyButton color="primary" type="submit">
Submit Form
</MyButton>
</form>
</>
);
};
Common Rules file
export const isRequired = (value: string) => {
return value ? true : 'This is a required input, can not escape';
}
export const maxLen = (value: string) => {
// console.log('Get values', getValues());
return value.length <= 15 || 'Value cannot be more than 15 chars';
}
const minLen = (value: string) => {
// console.log('Get values', getValues());
return value.length >= 7 || 'Value cannot be less than 7 chars';
}
const minMaxLen = (value: string) => { // Here i want to get dynamic parameter for min and max so that it can be used in various forms
return value.length >= <SomeMinValue> && value.length <= <SomeMaxValue> || 'Should be between ${SomeMinValue} and ${SomeMaxValue} chars';
}
const isValueEqual = (value: string) => {
const valOfFieldToBeComparedWith = getValues('password'); // Check how to pass params dynamically to validate function
console.log("retype password is", valOfFieldToBeComparedWith);
return value === valOfFieldToBeComparedWith || 'Password and retype password do not match';
}
export const ruleSet = {
isRequired,
minLen,
maxLen,
minMaxLen,
isValueEqual
}
I basically need a way to pass parameters to these functions defined in rules file so from the form component.
Any guidance will be highly appreciated. Thank you
Solution
You can wrap the validation function so that you can set the min/max params.
const makeMinMaxLen = (min: number, max: number) => (value: string) => {
return value.length >= min && value.length <= max || 'Should be between ${min} and ${max} chars';
}
<Controller
name="retype_password"
control={control}
rules={{ validate: {isRequired: ruleSet.isRequired, minMaxLen: ruleSet.makeMinMaxLen(4, 16), ruleSet.isValueEqual } }}
render={({ field, fieldState: {error}, formState }) =>
<MyTextField placeholder="Retype password here" error={!!error} {...field} />
}
/>
Even better is to store the composed function outside the render function
Answered By - Chris Answer Checked By - Timothy Miller (PHPFixing Admin)
0 Comments:
Post a Comment
Note: Only a member of this blog may post a comment.