Skip to content

Commit 0e7b1e7

Browse files
docs: add large form example (#1195)
* docs: add large form example * ci: apply automated fixes and generate docs --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
1 parent 796f975 commit 0e7b1e7

File tree

14 files changed

+354
-2
lines changed

14 files changed

+354
-2
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// @ts-check
2+
3+
/** @type {import('eslint').Linter.Config} */
4+
const config = {
5+
extends: ['plugin:react/recommended', 'plugin:react-hooks/recommended'],
6+
rules: {
7+
'react/no-children-prop': 'off',
8+
},
9+
}
10+
11+
module.exports = config

examples/react/large-form/.gitignore

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2+
3+
# dependencies
4+
/node_modules
5+
/.pnp
6+
.pnp.js
7+
8+
# testing
9+
/coverage
10+
11+
# production
12+
/build
13+
14+
pnpm-lock.yaml
15+
yarn.lock
16+
package-lock.json
17+
18+
# misc
19+
.DS_Store
20+
.env.local
21+
.env.development.local
22+
.env.test.local
23+
.env.production.local
24+
25+
npm-debug.log*
26+
yarn-debug.log*
27+
yarn-error.log*

examples/react/large-form/README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Example
2+
3+
To run this example:
4+
5+
- `npm install`
6+
- `npm run dev`

examples/react/large-form/index.html

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8" />
5+
<link rel="icon" type="image/svg+xml" href="/emblem-light.svg" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1" />
7+
<meta name="theme-color" content="#000000" />
8+
9+
<title>TanStack Form React Simple Example App</title>
10+
</head>
11+
<body>
12+
<noscript>You need to enable JavaScript to run this app.</noscript>
13+
<div id="root"></div>
14+
<script type="module" src="/src/index.tsx"></script>
15+
</body>
16+
</html>
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
{
2+
"name": "@tanstack/form-example-react-simple",
3+
"private": true,
4+
"type": "module",
5+
"scripts": {
6+
"dev": "vite --port=3001",
7+
"build": "vite build",
8+
"preview": "vite preview",
9+
"test:types": "tsc"
10+
},
11+
"dependencies": {
12+
"@tanstack/react-form": "^0.47.2",
13+
"react": "^19.0.0",
14+
"react-dom": "^19.0.0"
15+
},
16+
"devDependencies": {
17+
"@types/react": "^19.0.7",
18+
"@types/react-dom": "^19.0.3",
19+
"@vitejs/plugin-react": "^4.3.4",
20+
"vite": "^6.1.1"
21+
},
22+
"browserslist": {
23+
"production": [
24+
">0.2%",
25+
"not dead",
26+
"not op_mini all"
27+
],
28+
"development": [
29+
"last 1 chrome version",
30+
"last 1 firefox version",
31+
"last 1 safari version"
32+
]
33+
}
34+
}
Lines changed: 13 additions & 0 deletions
Loading

examples/react/large-form/src/App.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { PeoplePage } from './features/people/page.tsx'
2+
3+
export default function App() {
4+
return (
5+
<div>
6+
<PeoplePage />
7+
</div>
8+
)
9+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { withForm } from '../../hooks/form.tsx'
2+
import { peopleFormOpts } from './shared-form.tsx'
3+
4+
export const AddressFields = withForm({
5+
...peopleFormOpts,
6+
render: ({ form }) => {
7+
return (
8+
<div>
9+
<h2>Address</h2>
10+
<form.AppField
11+
name="address.line1"
12+
children={(field) => <field.TextField label="Address Line 1" />}
13+
/>
14+
<form.AppField
15+
name="address.line2"
16+
children={(field) => <field.TextField label="Address Line 2" />}
17+
/>
18+
<form.AppField
19+
name="address.city"
20+
children={(field) => <field.TextField label="City" />}
21+
/>
22+
<form.AppField
23+
name="address.state"
24+
children={(field) => <field.TextField label="State" />}
25+
/>
26+
<form.AppField
27+
name="address.zip"
28+
children={(field) => <field.TextField label="ZIP Code" />}
29+
/>
30+
</div>
31+
)
32+
},
33+
})
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { useAppForm } from '../../hooks/form.tsx'
2+
import { AddressFields } from './address-fields.tsx'
3+
import { peopleFormOpts } from './shared-form.tsx'
4+
5+
export const PeoplePage = () => {
6+
const form = useAppForm({
7+
...peopleFormOpts,
8+
validators: {
9+
onChange: ({ value }) => {
10+
const errors = {
11+
fields: {},
12+
} as {
13+
fields: Record<string, string>
14+
}
15+
if (!value.fullName) {
16+
errors.fields.fullName = 'Full name is required'
17+
}
18+
if (!value.phone) {
19+
errors.fields.phone = 'Phone is required'
20+
}
21+
if (!value.emergencyContact.fullName) {
22+
errors.fields['emergencyContact.fullName'] =
23+
'Emergency contact full name is required'
24+
}
25+
if (!value.emergencyContact.phone) {
26+
errors.fields['emergencyContact.phone'] =
27+
'Emergency contact phone is required'
28+
}
29+
30+
return errors
31+
},
32+
},
33+
onSubmit: ({ value }) => {
34+
alert(JSON.stringify(value, null, 2))
35+
},
36+
})
37+
38+
return (
39+
<form
40+
onSubmit={(e) => {
41+
e.preventDefault()
42+
form.handleSubmit()
43+
}}
44+
>
45+
<h1>Personal Information</h1>
46+
<form.AppField
47+
name="fullName"
48+
children={(field) => <field.TextField label="Full Name" />}
49+
/>
50+
<form.AppField
51+
name="email"
52+
children={(field) => <field.TextField label="Email" />}
53+
/>
54+
<form.AppField
55+
name="phone"
56+
children={(field) => <field.TextField label="Phone" />}
57+
/>
58+
<AddressFields form={form} />
59+
<h2>Emergency Contact</h2>
60+
<form.AppField
61+
name="emergencyContact.fullName"
62+
children={(field) => <field.TextField label="Full Name" />}
63+
/>
64+
<form.AppField
65+
name="emergencyContact.phone"
66+
children={(field) => <field.TextField label="Phone" />}
67+
/>
68+
<form.AppForm>
69+
<form.SubscribeButton label="Submit" />
70+
</form.AppForm>
71+
</form>
72+
)
73+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { formOptions } from '@tanstack/react-form'
2+
3+
export const peopleFormOpts = formOptions({
4+
defaultValues: {
5+
fullName: '',
6+
email: '',
7+
phone: '',
8+
address: {
9+
line1: '',
10+
line2: '',
11+
city: '',
12+
state: '',
13+
zip: '',
14+
},
15+
emergencyContact: {
16+
fullName: '',
17+
phone: '',
18+
},
19+
},
20+
})

0 commit comments

Comments
 (0)