T
TanStack•14mo ago
extended-salmon

Extracting form.Field logic and TypeScript issues

I am trying to create a component that will simplify the field creation. What should the extracted type for Field be? The intended use would be like this:
<FormField
Field={form.Field}
name="email"
label="Email"
tabIndex={1}
autoComplete="username"
/>
<FormField
Field={form.Field}
name="email"
label="Email"
tabIndex={1}
autoComplete="username"
/>
And the whole component I have right now is:
'use client'

import ErrorList from '@/components/error-list'
import { Flex, Text, TextField } from '@radix-ui/themes'
import { FieldComponent, Validator } from '@tanstack/react-form'
import { zodValidator } from '@tanstack/zod-form-adapter'

type Props = {
Field: FieldComponent<string | number | undefined, Validator<unknown, unknown> | unknown>
name: string
label: string
tabIndex?: number
type?:
| 'date'
| 'datetime-local'
| 'email'
| 'hidden'
| 'month'
| 'number'
| 'password'
| 'search'
| 'tel'
| 'text'
| 'time'
| 'url'
| 'week'
validators?: unknown
}

export default function FormFiled({ Field, name, label, type, tabIndex, validators }: Props) {
return (
<Field
name={name}
validatorAdapter={zodValidator()}
validators={validators}
children={({ state, handleBlur, handleChange }) => (
<Flex direction="column">
<Text as="label" size="2" weight="medium" mb="2" htmlFor={name}>
{label}
</Text>
<TextField.Root
variant="classic"
name={name}
type={type}
tabIndex={tabIndex}
defaultValue={state.value}
onBlur={handleBlur}
onChange={(e) => handleChange(e.target.value)}
/>
<ErrorList errors={state.meta.errors} />
</Flex>
)}
/>
)
}
'use client'

import ErrorList from '@/components/error-list'
import { Flex, Text, TextField } from '@radix-ui/themes'
import { FieldComponent, Validator } from '@tanstack/react-form'
import { zodValidator } from '@tanstack/zod-form-adapter'

type Props = {
Field: FieldComponent<string | number | undefined, Validator<unknown, unknown> | unknown>
name: string
label: string
tabIndex?: number
type?:
| 'date'
| 'datetime-local'
| 'email'
| 'hidden'
| 'month'
| 'number'
| 'password'
| 'search'
| 'tel'
| 'text'
| 'time'
| 'url'
| 'week'
validators?: unknown
}

export default function FormFiled({ Field, name, label, type, tabIndex, validators }: Props) {
return (
<Field
name={name}
validatorAdapter={zodValidator()}
validators={validators}
children={({ state, handleBlur, handleChange }) => (
<Flex direction="column">
<Text as="label" size="2" weight="medium" mb="2" htmlFor={name}>
{label}
</Text>
<TextField.Root
variant="classic"
name={name}
type={type}
tabIndex={tabIndex}
defaultValue={state.value}
onBlur={handleBlur}
onChange={(e) => handleChange(e.target.value)}
/>
<ErrorList errors={state.meta.errors} />
</Flex>
)}
/>
)
}
6 Replies
other-emerald
other-emerald•14mo ago
@Leonardo wanna tackle this and reference the WIP PR since I'm out?
extended-salmon
extended-salmonOP•14mo ago
@crutchcorn I have not opened that yet as a PR but that reminds me of my difficulties integrating the zod + nextjs-server-actions + ui-libraries example code... What do you think about me creating one 'advanced' example that combines these three into a realistically advanced demo (and some more like sharing code between client and sever validation etc.) and opening a PR ?
other-emerald
other-emerald•14mo ago
Sorry, I was saying that we already have a draft PR documenting this behavior 🙂
other-emerald
other-emerald•14mo ago
GitHub
[WIP] Shared Component Library Docs by crutchcorn · Pull Request #8...
This PR: Adds an example of moving TanStack Form into your own shared component library Adds the docs to explain what the example is doing
other-emerald
other-emerald•14mo ago
Open to feedback, of course! I'm just mostly unavail this week due to big family emergency
extended-salmon
extended-salmonOP•14mo ago
This looks very useful. Thank you for taking the time to respond! Oh, I now realize just yesterday searched on YouTube for TanStack Form content and watched the two videos by @Leonardo Awesome content, just subscribed.

Did you find this page helpful?