Skip to content

Commit aa83641

Browse files
committed
Add example
1 parent 22decc1 commit aa83641

8 files changed

Lines changed: 196 additions & 0 deletions

File tree

examples/preact/simple/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+
- `pnpm install`
6+
- `pnpm --filter @tanstack/form-example-preact-simple dev`

examples/preact/simple/index.html

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1" />
6+
<title>TanStack Form Preact Simple Example App</title>
7+
</head>
8+
<body>
9+
<div id="root"></div>
10+
<script type="module" src="/src/index.tsx"></script>
11+
</body>
12+
</html>
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"name": "@tanstack/form-example-preact-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/preact-form": "workspace:*",
13+
"preact": "^10.26.4"
14+
},
15+
"devDependencies": {
16+
"@preact/preset-vite": "^2.10.2",
17+
"vite": "^7.2.2"
18+
},
19+
"browserslist": {
20+
"production": [
21+
">0.2%",
22+
"not dead",
23+
"not op_mini all"
24+
],
25+
"development": [
26+
"last 1 chrome version",
27+
"last 1 firefox version",
28+
"last 1 safari version"
29+
]
30+
}
31+
}
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
import { render } from 'preact'
2+
3+
import { useForm } from '@tanstack/preact-form'
4+
5+
import type { AnyFieldApi } from '@tanstack/preact-form'
6+
7+
function FieldInfo({ field }: { field: AnyFieldApi }) {
8+
return (
9+
<>
10+
{field.state.meta.isTouched && !field.state.meta.isValid ? (
11+
<em>{field.state.meta.errors.join(',')}</em>
12+
) : null}
13+
{field.state.meta.isValidating ? 'Validating...' : null}
14+
</>
15+
)
16+
}
17+
18+
function App() {
19+
const form = useForm({
20+
defaultValues: {
21+
firstName: '',
22+
lastName: '',
23+
},
24+
onSubmit: async ({ value }) => {
25+
console.log(value)
26+
},
27+
})
28+
29+
return (
30+
<div>
31+
<h1>Simple Preact Form Example</h1>
32+
<form
33+
onSubmit={(e) => {
34+
e.preventDefault()
35+
e.stopPropagation()
36+
void form.handleSubmit()
37+
}}
38+
>
39+
<div>
40+
<form.Field
41+
name="firstName"
42+
validators={{
43+
onChange: ({ value }) =>
44+
!value
45+
? 'A first name is required'
46+
: value.length < 3
47+
? 'First name must be at least 3 characters'
48+
: undefined,
49+
}}
50+
children={(field) => (
51+
<>
52+
<label htmlFor={field.name}>First Name:</label>
53+
<input
54+
id={field.name}
55+
name={field.name}
56+
value={field.state.value}
57+
onBlur={field.handleBlur}
58+
onInput={(e) => field.handleChange(e.currentTarget.value)}
59+
/>
60+
<FieldInfo field={field} />
61+
</>
62+
)}
63+
/>
64+
</div>
65+
66+
<div>
67+
<form.Field
68+
name="lastName"
69+
children={(field) => (
70+
<>
71+
<label htmlFor={field.name}>Last Name:</label>
72+
<input
73+
id={field.name}
74+
name={field.name}
75+
value={field.state.value}
76+
onBlur={field.handleBlur}
77+
onInput={(e) => field.handleChange(e.currentTarget.value)}
78+
/>
79+
<FieldInfo field={field} />
80+
</>
81+
)}
82+
/>
83+
</div>
84+
85+
<form.Subscribe
86+
selector={(state) => [state.canSubmit, state.isSubmitting]}
87+
children={([canSubmit, isSubmitting]) => (
88+
<>
89+
<button type="submit" disabled={!canSubmit}>
90+
{isSubmitting ? '...' : 'Submit'}
91+
</button>
92+
<button
93+
type="reset"
94+
onClick={(e) => {
95+
e.preventDefault()
96+
form.reset()
97+
}}
98+
>
99+
Reset
100+
</button>
101+
</>
102+
)}
103+
/>
104+
</form>
105+
</div>
106+
)
107+
}
108+
109+
const rootElement = document.getElementById('root')
110+
111+
if (!rootElement) {
112+
throw new Error('Root element not found')
113+
}
114+
115+
render(<App />, rootElement)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"extends": "../../../tsconfig.json",
3+
"compilerOptions": {
4+
"jsx": "react-jsx",
5+
"jsxImportSource": "preact",
6+
"moduleResolution": "Bundler"
7+
},
8+
"include": ["src", "vite.config.ts"]
9+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { defineConfig } from 'vite'
2+
import preact from '@preact/preset-vite'
3+
4+
export default defineConfig({
5+
plugins: [preact()],
6+
})

pnpm-lock.yaml

Lines changed: 16 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pnpm-workspace.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ packages:
66
- packages/**
77
- examples/angular/**
88
- examples/react/**
9+
- examples/preact/**
910
- examples/solid/**
1011
- examples/vue/**
1112
- examples/lit/**

0 commit comments

Comments
 (0)