Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add rules to useFieldArray #6879

Closed
mmahalwy opened this issue Oct 24, 2021 · 17 comments · Fixed by #8562
Closed

Add rules to useFieldArray #6879

mmahalwy opened this issue Oct 24, 2021 · 17 comments · Fixed by #8562
Labels
feature request request a feature to be added

Comments

@mmahalwy
Copy link

Is your feature request related to a problem? Please describe.
Somewhat similar to this: #872

Describe the solution you'd like
Having the ability to add rules to the useFieldArray. For example, having a minimum number of items for a specific field array. This can be accomplished by adding schema with useForm but in the absence of that, having it on useFieldArray would be very useful.

Describe alternatives you've considered
Adding it to schema.

Additional context
Add any other context or screenshots about the feature request here.

@bluebill1049
Copy link
Member

thanks for the feature request. baby step, next release we will improve on schema: #6472 (comment) move to the project board and let's see if community do need this feature.

@bluebill1049 bluebill1049 added feature request request a feature to be added waiting-up-vote Waiting for votes from the community. labels Oct 24, 2021
@bluebill1049 bluebill1049 added this to Pending Feature Requests in React Hook Form Oct 24, 2021
@mmahalwy
Copy link
Author

@bluebill1049 if you point me in the right direction, I am happy to take this on

@bluebill1049
Copy link
Member

Thanks for offering help. I think there is a fundamental challenge that needs to be resolved before such a feature to be implemented. field array error {} vs [], if we are introducing rules at the field array level it's a question on how we deal with errors that need to be unlocked first.

@mmahalwy
Copy link
Author

Yeah, good point. In addition, there could be errors related to the array "this field needs to have a minimum of X" and errors related to individual items.

For unlocking, what is needed? Are you looking for ideas/suggestions here?

@mmahalwy
Copy link
Author

@bluebill1049 i thought of doing this with resolver, but as noted in this issue #1674, cannot have field level rules and resolver. I know that issue was back in 2020, is this still difficult?

@mmahalwy
Copy link
Author

@bluebill1049 ok, thinking more about this, here is my suggestion:

  • Add rules to useFieldArray. Those rules will be required, minLength, maxLength
  • We will also add validate as it matches validate for a field, but this will only validate the field array. Any errors will be merged with formState.errors as the name of the field array
  • We will introduce a validateArray or validateItems function that will accept fields as the argument return an record, with keys being the name of the field and value being the error. This will also be merged with formState.errors

This should hopefully solve separating field array error and fields error (so no need for [] vs {}) and give flexibility to do both.

Thoughts?

@mmahalwy
Copy link
Author

friendly bump :)

@bluebill1049
Copy link
Member

Thanks for the idea and input. Let's park this one for now until it gets more demands. For now, you can consider running that validation logic at useEffect with setError.

@mmahalwy
Copy link
Author

For anyone coming to see this, here's how i solved it for now:

export const useFieldArrayErrors = <T extends object>(
  fieldName: string,
  schema: Record<keyof T, ValidateTableRowsSchema<T>>
) => {
  let hasErrors = false;
  const { setError, clearErrors } = useFormContext();
  const fields = useWatch({ name: fieldName });

  const result = validateTableRows<T>(fields, schema);

  result.forEach((item, index) => {
    const keys = Object.keys(item) as (keyof T)[];
    keys.forEach((key) => {
      if (item[key]) {
        hasErrors = true;
        setError(`${fieldName}[${index}].${key}`, {
          type: 'manual',
          message: item[key],
        });
      } else {
        clearErrors(`${fieldName}[${index}].${key}`);
      }
    });
  });

  if (hasErrors) {
    setError(fieldName, {
      type: 'manual',
      message: 'Error with table fields',
    });
  } else {
    clearErrors(fieldName);
  }
};

@letsandeepio
Copy link

@mmahalwy This is great! Could you please add sandbox example to see how to use it !

@mmahalwy
Copy link
Author

mmahalwy commented Feb 4, 2022

I can! There's only one problem with it, and that if you expect errors to show up on submit, then this will always show the errors (doesnt have a hook into when a submission is triggered and to set the errors). Unless @bluebill1049 has a suggestion here, this will always show the errors

@letsandeepio
Copy link

@mmahalwy thanks I'll really appreciate the example code. I am curious about this behaviour -> validate on submit instead of whenever there are changes to the field. Is there workaround for this please? @bluebill1049

@letsandeepio
Copy link

@bluebill1049 am I missing something, is there another way of doing validations for useFieldArray? Using register or other way ? Where I can find example code. Thanks a lot 🙏

@giovannipiller
Copy link

giovannipiller commented Mar 9, 2022

Upvoting this as well.

Trying to setup validation with a useEffect and setError only works up to a certain point.

As @mmahalwy pointed out, there's no easy way to trigger that validation on submit.

For example, here I'm trying to setup a validation where at least 1 entry is required.

  const name = 'myField';

  const { fields, append, remove } = useFieldArray({ name });
  const {
    setError,
    clearErrors,
    formState: { errors, dirtyFields },
  } = useFormContext();

  {
    const fieldsLength = fields.length;
    useEffect(() => {
      if (dirtyFields[name] && fieldsLength === 0) {
        setError(name, { message: 'At least 1 entry is required' });
      } else {
        clearErrors(name);
      }
    }, [clearErrors, dirtyFields, fieldsLength, name, setError]);
  }

But there's no real way to trigger this useEffect on form submit.

@rowrowrowrow
Copy link

Upvote

@rowrowrowrow
Copy link

rowrowrowrow commented Jul 7, 2022

@bluebill1049 Will this also support the same value/message pattern for error messages as the existing register and rules?

@mmahalwy
Copy link
Author

@bluebill1049 thanks so much for making this happen!

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Oct 9, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
feature request request a feature to be added
Projects
Development

Successfully merging a pull request may close this issue.

5 participants