Array of strings
In this example, we use custom inputs to manage an array of string tags.
const schema = z.object({
title: z.string().min(1),
tags: z.array(z.string()).min(1),
})
const mutation = makeDomainFunction(schema)(async (values) => values)
export const action: ActionFunction = async ({ request }) =>
formAction({ request, schema, mutation })
export default () => {
const tagRef = useRef<HTMLInputElement>(null)
return (
<Form schema={schema} values={{ tags: [] }}>
{({ Field, Errors, Button, watch, setValue }) => {
const tags = watch('tags')
return (
<>
<Field name="title" />
<Field name="tags">
{({ Label, Errors }) => (
<>
<Label />
<input
type="text"
className="block w-full rounded-md border-gray-300 text-gray-800 shadow-sm
focus:border-pink-500 focus:ring-pink-500 sm:text-sm"
placeholder="Add a tag and press Enter..."
ref={tagRef}
onKeyDown={(event) => {
if (event.key === 'Enter') {
event.preventDefault()
if (tagRef.current) {
const value = tagRef.current.value
if (value) {
setValue(
'tags',
uniq([...(tags || []), value.toLowerCase()]),
{ shouldValidate: true },
)
}
tagRef.current.value = ''
}
}
}}
/>
{tags && (
<section className="-ml-1 flex flex-wrap pt-1">
{tags.map((tag) => (
<span key={tag}>
<span className="m-1 flex items-center rounded-md bg-pink-500 px-2 py-1 text-white">
<span className="flex-1">{tag}</span>
<button
className="ml-2 text-pink-700"
onClick={() => {
setValue(
'tags',
tags.filter((value) => tag !== value),
{ shouldValidate: true },
)
}}
>
X
</button>
</span>
<input type="hidden" name="tags[]" value={tag} />
</span>
))}
</section>
)}
<Errors />
</>
)}
</Field>
<Errors />
<Button />
</>
)
}}
</Form>
)
}
Array of strings
In this example, we use custom inputs to manage an array of string tags.
const schema = z.object({
title: z.string().min(1),
tags: z.array(z.string()).min(1),
})
const mutation = makeDomainFunction(schema)(async (values) => values)
export const action: ActionFunction = async ({ request }) =>
formAction({ request, schema, mutation })
export default () => {
const tagRef = useRef<HTMLInputElement>(null)
return (
<Form schema={schema} values={{ tags: [] }}>
{({ Field, Errors, Button, watch, setValue }) => {
const tags = watch('tags')
return (
<>
<Field name="title" />
<Field name="tags">
{({ Label, Errors }) => (
<>
<Label />
<input
type="text"
className="block w-full rounded-md border-gray-300 text-gray-800 shadow-sm
focus:border-pink-500 focus:ring-pink-500 sm:text-sm"
placeholder="Add a tag and press Enter..."
ref={tagRef}
onKeyDown={(event) => {
if (event.key === 'Enter') {
event.preventDefault()
if (tagRef.current) {
const value = tagRef.current.value
if (value) {
setValue(
'tags',
uniq([...(tags || []), value.toLowerCase()]),
{ shouldValidate: true },
)
}
tagRef.current.value = ''
}
}
}}
/>
{tags && (
<section className="-ml-1 flex flex-wrap pt-1">
{tags.map((tag) => (
<span key={tag}>
<span className="m-1 flex items-center rounded-md bg-pink-500 px-2 py-1 text-white">
<span className="flex-1">{tag}</span>
<button
className="ml-2 text-pink-700"
onClick={() => {
setValue(
'tags',
tags.filter((value) => tag !== value),
{ shouldValidate: true },
)
}}
>
X
</button>
</span>
<input type="hidden" name="tags[]" value={tag} />
</span>
))}
</section>
)}
<Errors />
</>
)}
</Field>
<Errors />
<Button />
</>
)
}}
</Form>
)
}