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

Validator Overhaul #527

Merged
merged 28 commits into from
Dec 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
6c85951
refactor!: move validators to prefixed property name
crutchcorn Dec 3, 2023
256d8cf
refactor!: rename validator to validatorAdapter
crutchcorn Dec 3, 2023
f70735c
chore: consolidate field validation logic
crutchcorn Dec 3, 2023
94df01d
fix: add missing field onSubmitAsyncDebounceMs value
crutchcorn Dec 3, 2023
f9067ab
chore: refactor form and field API validation mechanism to share code
crutchcorn Dec 3, 2023
d3d6280
feat: add submit, submitAsync validators to form
crutchcorn Dec 4, 2023
5b801cf
fix: onMount validator now works as expected
crutchcorn Dec 4, 2023
7ad392c
feat: add signal to async validations
crutchcorn Dec 4, 2023
ccb1891
refactor!: move onChange,onBlur,onMount,onSubmit props to pass object
crutchcorn Dec 4, 2023
1dc351e
refactor!: move submission function to take object instead of two arg…
crutchcorn Dec 5, 2023
9f4259f
chore: change throttled validation to debounce
crutchcorn Dec 5, 2023
75f10c0
chore: fix lib tests
crutchcorn Dec 5, 2023
20a0ecc
chore: fix typing inferencing
crutchcorn Dec 5, 2023
5c9667e
chore: fix typings
crutchcorn Dec 6, 2023
3fcd87d
chore: fix minor example typing issue
crutchcorn Dec 6, 2023
6b05329
chore: fix various typing issues with packages
crutchcorn Dec 6, 2023
09737bf
chore: move validators into util getters
crutchcorn Dec 10, 2023
97c7f6f
chore: cleaned up validator abstraction
crutchcorn Dec 10, 2023
b7b875c
test: add test for signal aborting
crutchcorn Dec 10, 2023
31ea38a
chore: fix various issues with Solid/core tests
crutchcorn Dec 10, 2023
c256b91
chore: temporarily disable Vue TS checking due to upstream bug
crutchcorn Dec 10, 2023
48eb032
chore: fix errors with TS in examples
crutchcorn Dec 10, 2023
aeefc02
docs: improve JS guides to TanStack Form
crutchcorn Dec 10, 2023
2da8845
docs: improve TypeScript docs
crutchcorn Dec 10, 2023
e94a21d
docs: add docs for form-level validation
crutchcorn Dec 10, 2023
e8c9f5a
docs: update and improve formApi docs
crutchcorn Dec 10, 2023
22b463c
docs: improve fieldApi reference
crutchcorn Dec 10, 2023
4a74b6e
docs: update reference docs for React
crutchcorn Dec 10, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/comparison.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ Feature/Capability Key:
| Nested object/array fields | ✅ | ❓ | ❓ | ❓ | ❓ |
| Async validation | ✅ | ❓ | ❓ | ❓ | ❓ |
| Built-in async validation debounce | ✅ | ❓ | ❓ | ❓ | ❓ |
| Schema-based Validation | 🔶 | ❓ | ❓ | ❓ | ❓ |
| Schema-based Validation | | ❓ | ❓ | ❓ | ❓ |

[bpl-tanstack-form]: https://bundlephobia.com/result?p=@tanstack/react-form
[bp-tanstack-form]: https://badgen.net/bundlephobia/minzip/@tanstack/react-form?label=💾
Expand Down
4 changes: 4 additions & 0 deletions docs/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@
{
"label": "FieldApi",
"to": "reference/fieldApi"
},
{
"label": "Types",
"to": "reference/types"
}
]
}
Expand Down
4 changes: 2 additions & 2 deletions docs/framework/react/quick-start.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ export default function App() {
defaultValues: {
fullName: '',
},
onSubmit: async (values) => {
onSubmit: async ({ value }) => {
// Do something with form data
console.log(values)
console.log(value)
},
})

Expand Down
67 changes: 36 additions & 31 deletions docs/framework/react/reference/Field.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,31 @@ id: field
title: Field
---

### `FieldComponent<TParentData>`
### `FieldComponent<TParentData, TFormValidator>`

A type alias representing a field component for a specific form data type.

```tsx
export type FieldComponent = <TField extends DeepKeys<TParentData>>({
export type FieldComponent<
TParentData,
TFormValidator extends
| Validator<TParentData, unknown>
| undefined = undefined,
> = <
TName extends DeepKeys<TParentData>,
TFieldValidator extends
| Validator<DeepValue<TParentData, TName>, unknown>
| undefined = undefined,
TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,
>({
children,
...fieldOptions
}: {
children: (
fieldApi: FieldApi<DeepValue<TParentData, TField>, TParentData>,
) => any
name: TField
} & Omit<
FieldOptions<DeepValue<TParentData, TField>, TParentData>,
'name'
}: FieldComponentProps<
TParentData,
TName,
TFieldValidator,
TFormValidator,
TData
>) => any
```

Expand All @@ -27,39 +36,35 @@ A function component that takes field options and a render function as children
### `Field`

```tsx
export function Field<TData, TParentData>({
export function Field<
TParentData,
TName extends DeepKeys<TParentData>,
TFieldValidator extends
| Validator<DeepValue<TParentData, TName>, unknown>
| undefined = undefined,
TFormValidator extends
| Validator<TParentData, unknown>
| undefined = undefined,
>({
children,
...fieldOptions
}: { children: (fieldApi: FieldApi<TData, TParentData>) => any } & FieldOptions<
TData,
TParentData
>): any
}: {
children: (
fieldApi: FieldApi<TParentData, TName, TFieldValidator, TFormValidator>,
) => any
} & UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator>): JSX.Element
```

A functional React component that renders a form field.

- ```tsx
children: (fieldApi: FieldApi<TData, TParentData>) => any
children: (fieldApi: FieldApi<TParentData, TName, TFieldValidator, TFormValidator>) => any
```
- A render function that takes a field API instance and returns a React element.
- ```tsx
fieldOptions: FieldOptions<TData, TParentData>
fieldOptions: UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator>
```
- The field options.

The `Field` component uses the `useField` hook internally to manage the field instance.

### `createFieldComponent`

```tsx
export function createFieldComponent<TParentData>(
formApi: FormApi<TParentData>,
): FieldComponent<TParentData>
```

A factory function that creates a connected field component for a specific form API instance.

- ```tsx
formApi: FormApi<TParentData>
```
- The form API instance to connect the field component to.
24 changes: 12 additions & 12 deletions docs/framework/react/reference/createFormFactory.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,34 @@ id: createFormFactory
title: createFormFactory
---

### `createFormFactory`
### `createFormFactory<TFormData, TFormValidator>`

```tsx
export function createFormFactory<TFormData>(
opts?: FormOptions<TFormData>,
): FormFactory<TFormData>
export function createFormFactory<TFormData, TFormValidator>(
opts?: FormOptions<TFormData, TFormValidator>,
): FormFactory<TFormData, TFormValidator>
```

A function that creates a new `FormFactory<TFormData>` instance.
A function that creates a new `FormFactory<TFormData, TFormValidator>` instance.

- `opts`
- Optional form options and a `listen` function to be called with the form state.
- Optional form options.

### `FormFactory<TFormData>`
### `FormFactory<TFormData, TFormValidator>`

A type representing a form factory. Form factories provide a type-safe way to interact with the form API as opposed to using the globally exported form utilities.

```tsx
export type FormFactory<TFormData> = {
useForm: (opts?: FormOptions<TFormData>) => FormApi<TFormData>
export type FormFactory<TFormData, TFormValidator> = {
useForm: (opts?: FormOptions<TFormData, TFormValidator>) => FormApi<TFormData>
useField: UseField<TFormData>
Field: FieldComponent<TFormData>
Field: FieldComponent<TFormData, TFormValidator>
}
```

- `useForm`
- A custom hook that creates and returns a new instance of the `FormApi<TFormData>` class.
- A custom hook that creates and returns a new instance of the `FormApi` class.
- `useField`
- A custom hook that returns an instance of the `FieldApi<TFormData>` class.
- A custom hook that returns an instance of the `FieldApi` class.
- `Field`
- A form field component.
6 changes: 3 additions & 3 deletions docs/framework/react/reference/fieldApi.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ id: fieldApi
title: Field API
---

### `FieldApi<TData, TParentData>`
### `FieldApi<TParentData, TName, TFieldValidator, TFormValidator, TData>`

When using `@tanstack/react-form`, the [core field API](../../reference/fieldApi) is extended with additional methods for React-specific functionality:
When using `@tanstack/react-form`, the [core field API](../../reference/fieldApi) is extended at type level with additional methods for React-specific functionality:

- ```tsx
Field: FieldComponent<TData, TParentData>
Field: FieldComponent<TParentData, TFormValidator>
```
- A pre-bound and type-safe sub-field component using this field as a root.
27 changes: 18 additions & 9 deletions docs/framework/react/reference/formApi.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,32 @@ id: formApi
title: Form API
---

### `FormApi<TFormData>`
### `FormApi<TFormData, TFormValidator>`

When using `@tanstack/react-form`, the [core form API](../../reference/formApi) is extended with additional methods for React-specific functionality:
When using `@tanstack/react-form`, the [core form API](../../reference/formApi) is extended at type level with additional methods for React-specific functionality:

- ```tsx
Field: FieldComponent<TFormData>
Provider: (props: PropsWithChildren) => JSX.Element
```
- A pre-bound and type-safe field component, specific to this forms instance.
- React provider use to wrap your components. Reference React's [ContextProvider]("https://react.dev/reference/react/createContext#provider")
- ```tsx
Field: FieldComponent<TFormData, TFormValidator>
```
- A React component to render form fields. With this, you can render and manage individual form fields.
- ```tsx
useField: UseField<TFormData>
```
- A pre-bound and type-safe custom hook to use fields from this form instance.
- A custom React hook that provides functionalities related to individual form fields. It gives you access to field values, errors, and allows you to set or update field values.
- ```tsx
useStore<TSelected = NoInfer<FormState<TFormData>>>(selector?: (state: NoInfer<FormState<TFormData>>) => TSelected): TSelected
useStore: <TSelected = NoInfer<FormState<TFormData>>>(
selector?: (state: NoInfer<FormState<TFormData>>) => TSelected,
) => TSelected
```
- A custom hook to use the form store.
- A `useStore` hook that connects to the internal store of the form. It can be used to access the form's current state or any other related state information. You can optionally pass in a selector function to cherry-pick specific parts of the state
- ```tsx
Subscribe<TSelected = NoInfer<FormState<TFormData>>>(props: {selector?: (state: NoInfer<FormState<TFormData>>) => TSelected; children: ((state: NoInfer<TSelected>) => React.ReactNode) | React.ReactNode}): any
Subscribe: <TSelected = NoInfer<FormState<TFormData>>>(props: {
selector?: (state: NoInfer<FormState<TFormData>>) => TSelected
children: ((state: NoInfer<TSelected>) => ReactNode) | ReactNode
}) => JSX.Element
```
- A subscription component to provide the selected form state to children.
- A `Subscribe` function that allows you to listen and react to changes in the form's state. It's especially useful when you need to execute side effects or render specific components in response to state updates.
55 changes: 35 additions & 20 deletions docs/framework/react/reference/useField.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,44 +8,59 @@ title: useField
A type representing a hook for using a field in a form with the given form data type.

```tsx
export type UseField = <TField extends DeepKeys<TParentData>>(
opts?: { name: TField } & FieldOptions<
DeepValue<TParentData, TField>,
TParentData
export type UseField<TParentData> = <
TName extends DeepKeys<TParentData>,
TFieldValidator extends
| Validator<DeepValue<TParentData, TName>, unknown>
| undefined = undefined,
TFormValidator extends
| Validator<TParentData, unknown>
| undefined = undefined,
>(
opts?: { name: Narrow<TName> } & UseFieldOptions<
TParentData,
TName,
TFieldValidator,
TFormValidator
>,
) => FieldApi<DeepValue<TParentData, TField>, TParentData>
) => FieldApi<
TParentData,
TName,
TFieldValidator,
TFormValidator,
DeepValue<TParentData, TName>
>
```

- A function that takes an optional object with a `name` property and field options, and returns a `FieldApi` instance for the specified field.

### `useField`

```tsx
export function useField<TData, TParentData>(
opts: FieldOptions<TData, TParentData>,
): FieldApi<TData, TParentData>
export function useField<
TParentData,
TName extends DeepKeys<TParentData>,
TFieldValidator extends
| Validator<DeepValue<TParentData, TName>, unknown>
| undefined = undefined,
TFormValidator extends
| Validator<TParentData, unknown>
| undefined = undefined,
>(
opts: UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator>,
): FieldApi<TParentData, TName, TFieldValidator, TFormValidator>
```

A hook for managing a field in a form.

- ```tsx
opts: FieldOptions<TData, TParentData>
opts: UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator>
```
- An object with field options.

#### Returns

- ```tsx
FieldApi<TData, TParentData>
FieldApi<TParentData, TName, TFieldValidator, TFormValidator>
```
- The `FieldApi` instance for the specified field.

### `createUseField`

```tsx
export function createUseField<TParentData>(
formApi: FormApi<TParentData>,
): UseField<TParentData>
```

A function that creates a `UseField` hook bound to the given `formApi`.
73 changes: 8 additions & 65 deletions docs/framework/react/reference/useForm.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,70 +6,13 @@ title: useForm
### `useForm`

```tsx
export function useForm<TData>(opts?: FormOptions<TData>): FormApi<TData>
```
A custom react hook that returns an instance of the `FormApi<TData>` class.
export function useForm<
TFormData,
TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,
>(
opts?: FormOptions<TFormData, TFormValidator>,
): FormApi<TFormData, TFormValidator>
```
A custom React Hook that returns an instance of the `FormApi` class.
This API encapsulates all the necessary functionalities related to the form. It allows you to manage form state, handle submissions, and interact with form fields



### `FormProps`

An object type representing the form component props.

- Inherits from `React.HTMLProps<HTMLFormElement>`.
- `children: React.ReactNode`
- The form's child elements.

```tsx
onSubmit: (e: FormSubmitEvent) => void
```
- `onSubmit` function of type `FormSubmitEvent = React.FormEvent<HTMLFormElement>`

```tsx
disabled: boolean
```
- `disabled` boolean to disable form



### Return value of `UseForm` is `FormApi<TFormData>`

- The `FormApi` contains the following properties

```tsx
Provider: (props: { children: any }) => any
```
- React provider use to wrap your components
- Reference React [ContextProvider]("https://react.dev/reference/react/createContext#provider")



```tsx
Field: FieldComponent<TFormData, TFormData>getFormProps: () => FormProps
```
- A React component to render form fields. With this, you can render and manage individual form fields.

```tsx
useField: UseField<TFormData>
```
- A custom React hook that provides functionalities related to individual form fields. It gives you access to field values, errors, and allows you to set or update field values.


```tsx
useStore: <TSelected = NoInfer<FormState<TFormData>>>(
selector?: (state: NoInfer<FormState<TFormData>>) => TSelected,
) => TSelected
```
- a `useStore` hook that connects to the internal store of the form. It can be used to access the form's current state or any other related state information. You can optionally pass in a selector function to cherry-pick specific parts of the state


```tsx
Subscribe: <TSelected = NoInfer<FormState<TFormData>>>(props: {
selector?: (state: NoInfer<FormState<TFormData>>) => TSelected
children:
| ((state: NoInfer<TSelected>) => React.ReactNode)
| React.ReactNode
}) => any
```
- a `Subscribe` function that allows you to listen and react to changes in the form's state. It's especially useful when you need to execute side effects or render specific components in response to state updates.
Loading