Write your answer here
Loading editor...
Dev4Room
Loading editor...
Search for a command to run...
Why does pandas.concat in Python 3.13 result in MemoryError with small DataFrames when using axis=1?
You can create a field config then map the over the fields that use the same component
Asked 4 months ago
1
412
1{profileFields.map((fieldConfig) => (
2 <Controller
3 key={fieldConfig.name}
4 name={fieldConfig.name}
5 control={form.control}
6 render=...
1{profileFields.map((fieldConfig) => (
2 <Controller
3 key={fieldConfig.name}
4 name={fieldConfig.name}
5 control={form.control}
6 render=...
I've read the docs about the implementation of Tanstack Form with shadcn Field component. But in their docs, all I saw was a bunch of boilerplate code. I want to implement a proper reusable form.
Here's there original template with Tanstack form:
1"use client"
2
3import * as React from "react"
4import { useForm } from "@tanstack/react-form"
5import { toast } from "sonner"
6import* as z from "zod"
7
8import { Button } from "@/components/ui/button"
9import {
10 Card,
11 CardContent,
12 CardDescription,
13 CardFooter,
14 CardHeader,
15 CardTitle,
16} from "@/components/ui/card"
17import {
18 Field,
19 FieldDescription,
20 FieldError,
21 FieldGroup,
22 FieldLabel,
23} from "@/components/ui/field"
24import { Input } from "@/components/ui/input"
25import {
26 InputGroup,
27 InputGroupAddon,
28 InputGroupText,
29 InputGroupTextarea,
30} from "@/components/ui/input-group"
31
32const formSchema = z.object({
33 title: z
34 .string()
35 .min(5, "Bug title must be at least 5 characters.")
36 .max(32, "Bug title must be at most 32 characters."),
37 description: z
38 .string()
39 .min(20, "Description must be at least 20 characters.")
40 .max(100, "Description must be at most 100 characters."),
41})
42
43export function BugReportForm() {
44 const form = useForm({
45 defaultValues: {
46 title: "",
47 description: "",
48 },
49 validators: {
50 onSubmit: formSchema,
51 },
52 onSubmit: async ({ value }) => {
53 toast("You submitted the following values:", {
54 description: (
55 <pre className="bg-code text-code-foreground mt-2 w-[320px] overflow-x-auto rounded-md p-4">
56 <code>{JSON.stringify(value, null, 2)}</code>
57 </pre>
58 ),
59 position: "bottom-right",
60 classNames: {
61 content: "flex flex-col gap-2",
62 },
63 style: {
64 "--border-radius": "calc(var(--radius) + 4px)",
65 } as React.CSSProperties,
66 })
67 },
68 })
69
70 return (
71 <Card className="w-full sm:max-w-md">
72 <CardHeader>
73 <CardTitle>Bug Report</CardTitle>
74 <CardDescription>
75 Help us improve by reporting bugs you encounter.
76 </CardDescription>
77 </CardHeader>
78 <CardContent>
79 <form
80 id="bug-report-form"
81 onSubmit={(e) => {
82 e.preventDefault()
83 form.handleSubmit()
84 }}
85 >
86 <FieldGroup>
87 <form.Field
88 name="title"
89 children={(field) => {
90 const isInvalid =
91 field.state.meta.isTouched && !field.state.meta.isValid
92 return (
93 <Field data-invalid={isInvalid}>
94 <FieldLabel htmlFor={field.name}>Bug Title</FieldLabel>
95 <Input
96 id={field.name}
97 name={field.name}
98 value={field.state.value}
99 onBlur={field.handleBlur}
100 onChange={(e) => field.handleChange(e.target.value)}
101 aria-invalid={isInvalid}
102 placeholder="Login button not working on mobile"
103 autoComplete="off"
104 />
105 {isInvalid && (
106 <FieldError errors={field.state.meta.errors} />
107 )}
108 </Field>
109 )
110 }}
111 />
112 <form.Field
113 name="description"
114 children={(field) => {
115 const isInvalid =
116 field.state.meta.isTouched && !field.state.meta.isValid
117 return (
118 <Field data-invalid={isInvalid}>
119 <FieldLabel htmlFor={field.name}>Description</FieldLabel>
120 <InputGroup>
121 <InputGroupTextarea
122 id={field.name}
123 name={field.name}
124 value={field.state.value}
125 onBlur={field.handleBlur}
126 onChange={(e) => field.handleChange(e.target.value)}
127 placeholder="I'm having an issue with the login button on mobile."
128 rows={6}
129 className="min-h-24 resize-none"
130 aria-invalid={isInvalid}
131 />
132 <InputGroupAddon align="block-end">
133 <InputGroupText className="tabular-nums">
134 {field.state.value.length}/100 characters
135 </InputGroupText>
136 </InputGroupAddon>
137 </InputGroup>
138 <FieldDescription>
139 Include steps to reproduce, expected behavior, and what
140 actually happened.
141 </FieldDescription>
142 {isInvalid && (
143 <FieldError errors={field.state.meta.errors} />
144 )}
145 </Field>
146 )
147 }}
148 />
149 </FieldGroup>
150 </form>
151 </CardContent>
152 <CardFooter>
153 <Field orientation="horizontal">
154 <Button type="button" variant="outline" onClick={() => form.reset()}>
155 Reset
156 </Button>
157 <Button type="submit" form="bug-report-form">
158 Submit
159 </Button>
160 </Field>
161 </CardFooter>
162 </Card>
163 )
164}
165
1"use client"
2
3import * as React from "react"
4import { useForm } from "@tanstack/react-form"
5import { toast } from "sonner"
6import* as z from "zod"
7
8import { Button } from "@/components/ui/button"
9import {
10 Card,
11 CardContent,
12 CardDescription,
13 CardFooter,
14 CardHeader,
15 CardTitle,
16} from "@/components/ui/card"
17import {
18 Field,
19 FieldDescription,
20 FieldError,
21 FieldGroup,
22 FieldLabel,
23} from "@/components/ui/field"
24import { Input } from "@/components/ui/input"
25import {
26 InputGroup,
27 InputGroupAddon,
28 InputGroupText,
29 InputGroupTextarea,
30} from "@/components/ui/input-group"
31
32const formSchema = z.object({
33 title: z
34 .string()
35 .min(5, "Bug title must be at least 5 characters.")
36 .max(32, "Bug title must be at most 32 characters."),
37 description: z
38 .string()
39 .min(20, "Description must be at least 20 characters.")
40 .max(100, "Description must be at most 100 characters."),
41})
42
43export function BugReportForm() {
44 const form = useForm({
45 defaultValues: {
46 title: "",
47 description: "",
48 },
49 validators: {
50 onSubmit: formSchema,
51 },
52 onSubmit: async ({ value }) => {
53 toast("You submitted the following values:", {
54 description: (
55 <pre className="bg-code text-code-foreground mt-2 w-[320px] overflow-x-auto rounded-md p-4">
56 <code>{JSON.stringify(value, null, 2)}</code>
57 </pre>
58 ),
59 position: "bottom-right",
60 classNames: {
61 content: "flex flex-col gap-2",
62 },
63 style: {
64 "--border-radius": "calc(var(--radius) + 4px)",
65 } as React.CSSProperties,
66 })
67 },
68 })
69
70 return (
71 <Card className="w-full sm:max-w-md">
72 <CardHeader>
73 <CardTitle>Bug Report</CardTitle>
74 <CardDescription>
75 Help us improve by reporting bugs you encounter.
76 </CardDescription>
77 </CardHeader>
78 <CardContent>
79 <form
80 id="bug-report-form"
81 onSubmit={(e) => {
82 e.preventDefault()
83 form.handleSubmit()
84 }}
85 >
86 <FieldGroup>
87 <form.Field
88 name="title"
89 children={(field) => {
90 const isInvalid =
91 field.state.meta.isTouched && !field.state.meta.isValid
92 return (
93 <Field data-invalid={isInvalid}>
94 <FieldLabel htmlFor={field.name}>Bug Title</FieldLabel>
95 <Input
96 id={field.name}
97 name={field.name}
98 value={field.state.value}
99 onBlur={field.handleBlur}
100 onChange={(e) => field.handleChange(e.target.value)}
101 aria-invalid={isInvalid}
102 placeholder="Login button not working on mobile"
103 autoComplete="off"
104 />
105 {isInvalid && (
106 <FieldError errors={field.state.meta.errors} />
107 )}
108 </Field>
109 )
110 }}
111 />
112 <form.Field
113 name="description"
114 children={(field) => {
115 const isInvalid =
116 field.state.meta.isTouched && !field.state.meta.isValid
117 return (
118 <Field data-invalid={isInvalid}>
119 <FieldLabel htmlFor={field.name}>Description</FieldLabel>
120 <InputGroup>
121 <InputGroupTextarea
122 id={field.name}
123 name={field.name}
124 value={field.state.value}
125 onBlur={field.handleBlur}
126 onChange={(e) => field.handleChange(e.target.value)}
127 placeholder="I'm having an issue with the login button on mobile."
128 rows={6}
129 className="min-h-24 resize-none"
130 aria-invalid={isInvalid}
131 />
132 <InputGroupAddon align="block-end">
133 <InputGroupText className="tabular-nums">
134 {field.state.value.length}/100 characters
135 </InputGroupText>
136 </InputGroupAddon>
137 </InputGroup>
138 <FieldDescription>
139 Include steps to reproduce, expected behavior, and what
140 actually happened.
141 </FieldDescription>
142 {isInvalid && (
143 <FieldError errors={field.state.meta.errors} />
144 )}
145 </Field>
146 )
147 }}
148 />
149 </FieldGroup>
150 </form>
151 </CardContent>
152 <CardFooter>
153 <Field orientation="horizontal">
154 <Button type="button" variant="outline" onClick={() => form.reset()}>
155 Reset
156 </Button>
157 <Button type="submit" form="bug-report-form">
158 Submit
159 </Button>
160 </Field>
161 </CardFooter>
162 </Card>
163 )
164}
165