Skip to content

Commit 78be5bd

Browse files
docs: add additional docs for Lit (#878)
* chore: pulling * feat: add quickstart and guide for lit docs * feat: add lit arrays docs * feat: add lit arrays docs * feat: add basic concepts docs * chore: pulling * feat: add lit docs * docs: get PR to stable place --------- Co-authored-by: Corbin Crutchley <[email protected]>
1 parent d5e06c7 commit 78be5bd

File tree

9 files changed

+346
-35
lines changed

9 files changed

+346
-35
lines changed

LICENSE

100644100755
File mode changed.

codecov.yml

100644100755
File mode changed.

docs/config.json

+14-1
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,19 @@
197197
"to": "framework/solid/guides/linked-fields"
198198
}
199199
]
200+
},
201+
{
202+
"label": "lit",
203+
"children": [
204+
{
205+
"label": "Basic Concepts",
206+
"to": "framework/lit/guides/basic-concepts"
207+
},
208+
{
209+
"label": "Arrays",
210+
"to": "framework/lit/guides/arrays"
211+
}
212+
]
200213
}
201214
]
202215
},
@@ -385,7 +398,7 @@
385398
},
386399
{
387400
"label": "Classes / TanStackFormController",
388-
"to": "framework/lit/reference/classes/tanstackformcontroller"
401+
"to": "framework/lit/reference/tanstackformcontroller"
389402
}
390403
]
391404
},

docs/framework/lit/guides/arrays.md

+181
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
---
2+
id: arrays
3+
title: Arrays
4+
---
5+
6+
TanStack Form supports arrays as values in a form, including sub-object values inside of an array.
7+
8+
# Basic Usage
9+
10+
To use an array, you can use `field.state.value` on an array value, as in:
11+
12+
```ts
13+
export class TestForm extends LitElement {
14+
#form = new TanStackFormController(this, {
15+
defaultValues: {
16+
people: [] as Array<{ name: string; age: string }>,
17+
},
18+
})
19+
render() {
20+
return html`
21+
<form
22+
id="form"
23+
@submit=${(e: Event) => {
24+
e.preventDefault()
25+
}}
26+
>
27+
<h1>Please enter your details</h1>
28+
${this.#form.field(
29+
{
30+
name: `people`,
31+
},
32+
(peopleField) => {
33+
return html`${repeat(
34+
peopleField.state.value,
35+
(_, index) => index,
36+
(_, index) => {
37+
return html` // ... `
38+
},
39+
)} `
40+
},
41+
)}
42+
</form>
43+
`
44+
}
45+
}
46+
```
47+
48+
This will generate the mapped HTML every time you run pushValue on the field:
49+
50+
51+
```html
52+
<div class="container">
53+
<button
54+
type="button"
55+
@click=${() => {
56+
peopleField.pushValue({name: "",age: ""})
57+
}}>
58+
Add Person
59+
</button>
60+
</div>
61+
```
62+
63+
Finally, you can use a subfield like so:
64+
65+
```ts
66+
return html`
67+
${this.#form.field(
68+
{
69+
name: `people[${index}].name`,
70+
},
71+
(field) => {
72+
return html`
73+
<input
74+
type="text"
75+
placeholder="Name"
76+
.value="${field.state.value}"
77+
@input="${(e: Event) => {
78+
const target = e.target as HTMLInputElement;
79+
field.handleChange(target.value);
80+
}}"
81+
/>
82+
`;
83+
},
84+
)}
85+
`
86+
```
87+
88+
89+
## Full Example
90+
91+
92+
```typescript
93+
export class TestForm extends LitElement {
94+
#form = new TanStackFormController(this, {
95+
defaultValues: {
96+
people: [] as Array<{ name: string}>,
97+
},
98+
});
99+
render() {
100+
return html`
101+
<form
102+
id="form"
103+
@submit=${(e: Event) => {
104+
e.preventDefault();
105+
}}
106+
>
107+
<h1>Please enter your details</h1>
108+
${this.#form.field(
109+
{
110+
name: `people`,
111+
},
112+
(peopleField) => {
113+
return html`${repeat(
114+
peopleField.state.value,
115+
(_, index) => index,
116+
(_, index) => {
117+
return html`
118+
${this.#form.field(
119+
{
120+
name: `people[${index}].name`,
121+
},
122+
(field) => {
123+
return html` <div>
124+
<div class="container">
125+
<label>Name</label>
126+
<input
127+
type="text"
128+
placeholder="Name"
129+
.value="${field.state.value}"
130+
@input="${(e: Event) => {
131+
const target = e.target as HTMLInputElement;
132+
field.handleChange(target.value);
133+
}}"
134+
/>
135+
</div>
136+
</div>`;
137+
}
138+
)}
139+
`;
140+
}
141+
)}
142+
143+
<div class="container">
144+
<button
145+
type="button"
146+
@click=${() => {
147+
peopleField.pushValue({
148+
name: "",
149+
});
150+
}}
151+
>
152+
Add Person
153+
</button>
154+
</div> `;
155+
}
156+
)}
157+
158+
<div class="container">
159+
<button type="submit" ?disabled=${this.#form.api.state.isSubmitting}>
160+
${this.#form.api.state.isSubmitting ? html` Submitting` : "Submit"}
161+
</button>
162+
<button
163+
type="button"
164+
id="reset"
165+
@click=${() => {
166+
this.#form.api.reset();
167+
}}
168+
>
169+
Reset
170+
</button>
171+
</div>
172+
</form>
173+
`;
174+
}
175+
176+
declare global {
177+
interface HTMLElementTagNameMap {
178+
"test-form": TestForm;
179+
}
180+
}
181+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
---
2+
id: basic-concepts
3+
title: Basic Concepts and Terminology
4+
---
5+
6+
This page introduces the basic concepts and terminology used in the `@tanstack/lit-form` library. Familiarizing yourself with these concepts will help you better understand and work with the library and its usage with Lit.
7+
8+
## Form Options
9+
10+
You can create options for your form so that it can be shared between multiple forms by using the `formOptions` function.
11+
12+
For Example:
13+
14+
```tsx
15+
const formOpts = formOptions({
16+
defaultValues: {
17+
firstName: '',
18+
lastName: '',
19+
employed: false,
20+
jobTitle: '',
21+
} as Employee,
22+
})
23+
```
24+
25+
## Form Instance
26+
27+
A Form Instance is an object that represents an individual form and provides methods and properties for working with the form. You create a form instance using the `TanStackFormController` interface provided by `@tanstack/lit-form`. The `TanStackFormController` is instantiated with the current form's (`this`) class and some default form options. It initializes the form state, handles form submission, and provides methods to manage form fields and their validation.
28+
29+
```tsx
30+
#form = new TanStackFormController(this, {
31+
defaultValues: {
32+
firstName: '',
33+
lastName: '',
34+
employed: false,
35+
jobTitle: '',
36+
} as Employee,
37+
})
38+
```
39+
40+
You may also create a form instance without using `formOptions` by using the standalone `TanStackFormController` API:
41+
42+
```tsx
43+
#form = new TanStackFormController(this, {
44+
...formOpts,
45+
})
46+
```
47+
48+
## Field
49+
50+
A Field represents a single form input element, such as a text input or a checkbox. Fields are created using the `field(FieldOptions, callback)` provided by the form instance. The component accepts a `FieldOptions` object and a callback function that receives a `FieldApi` object. This object provides methods to get the current value of the field, handle input changes, and handle blur events.
51+
52+
For Example:
53+
54+
```ts
55+
${this.#form.field(
56+
{
57+
name: `firstName`,
58+
validators: {
59+
onChange: ({ value }) =>
60+
value.length < 3 ? "Not long enough" : undefined,
61+
},
62+
},
63+
(field: FieldApi<Employee, "firstName">) => {
64+
return html` <div>
65+
<label class="first-name-label">First Name</label>
66+
<input
67+
id="firstName"
68+
type="text"
69+
class="first-name-input"
70+
placeholder="First Name"
71+
@blur="${() => field.handleBlur()}"
72+
.value="${field.state.value}"
73+
@input="${(event: InputEvent) => {
74+
if (event.currentTarget) {
75+
const newValue = (event.currentTarget as HTMLInputElement).value;
76+
field.handleChange(newValue);
77+
}
78+
}}"
79+
/>
80+
</div>`;
81+
},
82+
)}
83+
```
84+
85+
## Field State
86+
87+
Each field has its own state, which includes its current value, validation status, error messages, and other metadata. You can access a field's state using its `field.state` property.
88+
89+
```tsx
90+
const { value, meta: { errors, isValidating } } = field.state
91+
```
92+
93+
There are three field states can be very useful to see how the user interacts with a field. A field is _"touched"_ when the user clicks/tabs into it, _"pristine"_ until the user changes value in it, and _"dirty"_ after the value has been changed. You can check these states via the `isTouched`, `isPristine` and `isDirty` flags, as seen below.
94+
95+
```tsx
96+
const { isTouched, isPristine, isDirty } = field.state.meta
97+
```
98+
99+
![Field states](https://raw.githubusercontent.com/TanStack/form/main/docs/assets/field-states.png)

0 commit comments

Comments
 (0)