Skip to content

Commit

Permalink
Merge pull request #44 from stevent-team/feat/set-errors
Browse files Browse the repository at this point in the history
`setErrors` function
  • Loading branch information
GRA0007 authored Aug 18, 2023
2 parents d24dfaa + 474563b commit 2a9c6fa
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 1 deletion.
5 changes: 5 additions & 0 deletions .changeset/great-pants-peel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@stevent-team/react-zoom-form": minor
---

Add `setError` function to manually set or clear form errors
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,17 @@ You can customize the error messages in several ways.
```
</details>

#### Manually Set and Clear Errors

Use the `setError` function to set or clear errors for a particular field, or the entire form.

```tsx
setError(fields.image, { code: 'custom', message: 'Server failed to upload' })

// Clear all errors
setError(fields, undefined)
```

### Coercion and Validation

Importantly, native HTML `input`, `textarea` and `select` all use strings to store their values. Because of this, `undefined` or `null` are not valid values for native fields, and the following schema defines a string that is _not_ required*.
Expand Down
23 changes: 23 additions & 0 deletions lib/field.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export type Field<Schema extends z.ZodType = z.ZodType> = {
formValue: React.MutableRefObject<RecursivePartial<z.TypeOf<Schema>>>
setFormValue: React.Dispatch<React.SetStateAction<RecursivePartial<z.ZodType>>>
formErrors: z.ZodError<z.ZodType> | undefined
setFormErrors: React.Dispatch<React.SetStateAction<z.ZodError<z.ZodType> | undefined>>
}
}

Expand Down Expand Up @@ -78,6 +79,28 @@ export const controlled = <T>({ _field }: Field<z.ZodType<T>>): ControlledField<
export const fieldErrors = <T>({ _field: { formErrors, path } }: Field<z.ZodType<T>>): z.ZodIssue[] =>
formErrors?.issues?.filter(issue => arrayStartsWith(issue.path, path.map(p => p.key))) ?? []

/**
* Set an error for a field. Will clear any existing errors for or below the field provided.
*
* @example
* ```tsx
* setError(fields.image, { code: 'custom', message: 'Server failed to upload' })
* setError(fields, undefined) // Clear all errors
* ```
*/
export const setError = <T>({ _field: { setFormErrors, path } }: Field<z.ZodType<T>>, issue: Omit<z.ZodIssue, 'path'> | undefined) => {
// Clear all
if (issue === undefined && path.length === 0) return setFormErrors(undefined)

setFormErrors(formErrors => z.ZodError.create([
...formErrors?.issues?.filter(issue => !arrayStartsWith(issue.path, path.map(p => p.key))) ?? [],
...issue !== undefined ? [{
...issue as z.ZodIssue,
path: path.map(s => s.key),
}] : [],
]))
}

/**
* Get the value of a field. You can also use the base `fields` object to
* watch all values in the form.
Expand Down
2 changes: 1 addition & 1 deletion lib/useForm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ export const useForm = <Schema extends z.ZodTypeAny>({
}, [validate])

const fields = useMemo(() => new Proxy({}, {
get: (_target, key) => fieldChain(schema, [], register, fieldRefs, { formValue, setFormValue, formErrors })[key]
get: (_target, key) => fieldChain(schema, [], register, fieldRefs, { formValue, setFormValue, formErrors, setFormErrors })[key]
}) as unknown as FieldChain<Schema>, [schema, setFormValue, formErrors])

return {
Expand Down

0 comments on commit 2a9c6fa

Please sign in to comment.