0

I am trying to use React Hook Form to setup a custom input field and thus use the useForm hook as below;

const {
        control,
        handleSubmit,
        register,
        formState,
        setValue,
        getValues
    } = useForm({
        mode: 'onSubmit',
        reValidateMode: 'onSubmit',
        shouldFocusError: true,
        defaultValues: {
            myIdFld: '123'
        },
        resolver: yupResolver(schema)
    });

const onSubmit = (data) => {
        alert(JSON.stringify(data));
    };
    const onErrors = (data) => {
        alert('Errors !');
    };

I have a field config js as below;

let sampleField = {"id":"myIdFld","mandatory":true,"visible":true,"maxLength":5,"items":[],"gridItems":[],"disabled":false,"hidden":false,"readonly":false,"fieldLabel":"My ID 1","pattern":/[A-Za-z]{3}/,"editable":true};

I use the above and pass it to my custom Field component JSX as below;

return (
<>
        <form
            onSubmit={handleSubmit((data) => console.log('Save Successful ', data))}>
            <Field name={sampleField.id} control={control} label={sampleField.fieldLabel} formFieldProps={{ necessity: (sampleField.mandatory === true) ?'required': 'optional' }} field={sampleField} {...props} />
      <Button onClick={handleSubmit(onSubmit, onErrors)} type="submit" variant="cta">Submit</Button>
    </form>
</>
)

My Field component JSX is as below;

import { Controller } from "react-hook-form"
          
<Controller
    control={control}
    rules={{required: "The field is required"}}
    name={name}
    render={({ field: { ref, ...restField }, fieldState: { error } }) => {
        const validationMessage = error ? error.message : helperText;
        const validationStatus = error && 'error';
        return (
            <FormField validationStatus={validationStatus} {...formFieldProps}>
            <FormFieldLabel {...formFieldLabelProps}>
                {label}
            </FormFieldLabel>
            <Input
                inputRef={ref}
                {...restField}
                {...restProps}
            />
            <FormFieldHelperText>{validationMessage}</FormFieldHelperText>
            </FormField>
        );
    }}
/>        

My Input is kind of a custom controlled component and I am trying to integrate via Controller

Now, the issue is while on submit, I do get the value which I enter in the textbox alerted (which means the field is getting registered). But I am not able to add any validations and cannot get the error object populated.

Please suggest what I need to add in the above code so that the validations/errors can be integrated. Ideally, I am wanting to use the sampleField config js for validation purpose (since it would have attributes like mandatory: true, regex/pattern, etc ...though, I am not sure if I also need to provide the custom error messages.

If yes, I am not sure where can I add those error configurations.

I already tried adding below and passing rules={createValidationRules(field)} to Field;

const createValidationRules = (fieldConfig) => {
        const rules = {};
        if (fieldConfig.mandatory) {
            rules.required = fieldConfig.customRequiredMessage || "This field is required";
        }
        if (fieldConfig.pattern) {            
            rules.pattern = {
                value: fieldConfig.pattern,
                message: fieldConfig.customPatternMessage || "Invalid format"
            };
        }
        if (fieldConfig.maxLength) {
            rules.maxLength = {
                value: fieldConfig.maxLength,
                message: fieldConfig.customMaxLengthMessage || `Maximum length is ${fieldConfig.maxLength}`
            };
        }
        return rules;
    };

But still does not work.

1 Answer 1

1

Okay i looked into your Input component and you could try it this way:

  1. Change your Field like this:
const Field = ({ name, control, label, formFieldProps, field }) => {
    // dynamic validation rules
    const validationRules = {
        required: field.mandatory ? "This field is required" : false,
        maxLength: field.maxLength ? {
        value: field.maxLength,
        message: `Max length is ${field.maxLength} characters`
    } : undefined,
        pattern: field.pattern ? {
            value: field.pattern,
            message: `Invalid format`
    } : undefined,
    };
    return (
        <Controller
            control={control}
            name={name}
            rules={validationRules}
            render={({ field: { ref, ...restField }, fieldState: { error } }) => {
        const validationMessage = error ? error.message : '';  // Error Messages
        const validationStatus = error ? 'error' : undefined;
        return (
            <FormField validationStatus={validationStatus} {...formFieldProps}>
                <FormFieldLabel>{label}</FormFieldLabel>
                <Input inputRef={ref} {...restField} />
                {error && <FormFieldHelperText>{validationMessage}</FormFieldHelperText>}
            </FormField>
            );
        }}
        />
    ); };
  1. use handleSubmit to handle onSubmit and onErrors:
<form onSubmit={handleSubmit(onSubmit, onErrors)}>
    <Field 
    name={sampleField.id} 
    control={control} 
    label={sampleField.fieldLabel} 
    formFieldProps={{ necessity: (sampleField.mandatory === true) ? 'required' : 'optional' }} 
    field={sampleField} 
    {...props} 
    />
    <Button type="submit" variant="cta">Submit</Button>
</form>

I dont know if thats the issue but react-hook-form does things the way react-hook-form wants to do, so you are gonna have to try different ways until it works.

Sign up to request clarification or add additional context in comments.

7 Comments

Thanks. Again, I get the alert with empty string for the input if I keep it empty. However, I do not see the error. Not sure if there is anything to do with register. I can share my Input component code link if you would like to look into that.
Sure maybe I could find the problem
Again, I am consuming the above Input via Controller I have shown above
Im sorry I dont really get why it won't work right. Your input component looks good and you integrated react hook form the right way. Idk I would love to help. I will look into it a bit more and text you if I got something
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.