Skip to content

Commit 5b28402

Browse files
committed
Copy from github wiki
1 parent de8b24b commit 5b28402

25 files changed

+1721
-0
lines changed

articles/Array-fields.md

Lines changed: 249 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,249 @@
1+
To create dynamic array fields, you should use the [`ArrayForm`](https://github.com/CodeStix/typed-react-form/wiki/ArrayForm) component or [`useArrayForm`](https://github.com/CodeStix/typed-react-form/wiki/useArrayForm) hook. These are wrappers around [`useChildForm`](https://github.com/CodeStix/typed-react-form/wiki/useChildForm) which provide useful functions and optimizations for arrays.
2+
3+
- [ArrayForm](https://github.com/CodeStix/typed-react-form/wiki/ArrayForm)
4+
- [useArrayForm](https://github.com/CodeStix/typed-react-form/wiki/useArrayForm)
5+
6+
If you have an array field with a constant size, you should probably just use [`ChildForm`](https://github.com/CodeStix/typed-react-form/wiki/ChildForm). (See bottom for examples)
7+
8+
**Note on keys**: you **should** use the index as key, this seems against nature at first, but remember that this library does not rerender each time something in the array changes. When 2 array items get swapped, it does not rerender either, only when the array size changes, it rerenders. For this reason, it is not a problem (and it's recommended) to use index as the key. (This can change in the future)
9+
10+
## Dynamic array examples
11+
12+
✔️ **Dynamic string array field using `ArrayForm`**
13+
```jsx
14+
function NotesList() {
15+
const form = useForm({
16+
notes: ["Do the dishes", "Go outside", "Drink some water"]
17+
});
18+
return (
19+
<form
20+
onSubmit={(ev) => {
21+
ev.preventDefault();
22+
console.log("submit", form.values);
23+
}}
24+
>
25+
<ArrayForm
26+
parent={form}
27+
name="notes"
28+
render={({ form, values, append, remove }) => (
29+
<>
30+
{values.map((_, i) => ( // You SHOULD use index as key. See top for info.
31+
<div key={i}>
32+
<FormInput form={form} name={i} />
33+
<button type="button" onClick={() => remove(i)}>
34+
Remove
35+
</button>
36+
</div>
37+
))}
38+
<button type="button" onClick={() => append("New note")}>
39+
Add note
40+
</button>
41+
</>
42+
)}
43+
/>
44+
<button>Submit</button>
45+
</form>
46+
);
47+
}
48+
```
49+
50+
✔️ **Dynamic object array field using `ArrayForm`**
51+
52+
Remember: this is all type checked!
53+
54+
```jsx
55+
function ShoppingListForm() {
56+
const form = useForm({
57+
title: "My shopping list",
58+
items: [{ name: "Coffee", amount: 1 }]
59+
});
60+
61+
return (
62+
<form
63+
onSubmit={(ev) => {
64+
ev.preventDefault();
65+
console.log("submit", form.values);
66+
}}
67+
>
68+
<h2>Title</h2>
69+
<FormInput form={form} type="text" name="title" />
70+
71+
<h2>Items</h2>
72+
<ArrayForm // Create an array child form for the 'items' field
73+
parent={form}
74+
name="items"
75+
render={({ form, values, append, remove }) => (
76+
<>
77+
{/* This only rerenders when the whole array changes. */}
78+
79+
{values.map((_, i) => (
80+
<ChildForm // Create a child form for each item in the array, because each array item is an object.
81+
key={i} // You should index as key
82+
parent={form} // Pass the parent form
83+
name={i} // Pass the current index as the name
84+
render={(form) => (
85+
<div>
86+
{/* Everything here is type-checked! */}
87+
<FormInput form={form} type="text" name="name" />
88+
<FormInput form={form} type="number" name="amount" />
89+
<button type="button" onClick={() => remove(i)}>
90+
Remove
91+
</button>
92+
</div>
93+
)}
94+
/>
95+
))}
96+
97+
{/* Use the append helper function to add an item to the array */}
98+
<button type="button" onClick={() => append({ name: "", amount: 1 })}>
99+
Add item
100+
</button>
101+
</>
102+
)}
103+
/>
104+
<button>Submit</button>
105+
</form>
106+
);
107+
}
108+
```
109+
110+
✔️ **Dynamic object array field with seperate component for each child form and using `useArrayForm`**
111+
```jsx
112+
interface ShoppingListItem {
113+
name: string;
114+
amount: number;
115+
}
116+
interface ShoppingList {
117+
title: string;
118+
items: ShoppingListItem[];
119+
}
120+
121+
function ShoppingListForm() {
122+
const form = useForm<ShoppingList>({
123+
title: "My shopping list",
124+
items: [{ name: "Coffee", amount: 1 }]
125+
});
126+
return (
127+
<form
128+
onSubmit={(ev) => {
129+
ev.preventDefault();
130+
console.log("submit", form.values);
131+
}}
132+
>
133+
<h2>Title</h2>
134+
<FormInput form={form} type="text" name="title" />
135+
<h2>Items</h2>
136+
<ShoppingListItemsForm parent={form} />
137+
<button>Submit</button>
138+
</form>
139+
);
140+
}
141+
142+
function ShoppingListItemsForm(props: { parent: FormState<ShoppingList> }) {
143+
const { form, values, append, remove } = useArrayForm(props.parent, "items");
144+
// This component only rerenders when the whole array changes.
145+
return (
146+
<>
147+
{values.map((_, i) => (
148+
<ShoppingListItemForm parent={form} index={i} key={i} remove={remove} />
149+
))}
150+
<button type="button" onClick={() => append({ name: "", amount: 1 })}>
151+
Add item
152+
</button>
153+
</>
154+
);
155+
}
156+
157+
function ShoppingListItemForm(props: { parent: FormState<ShoppingListItem[]>; index: number; remove: (i: number) => void }) {
158+
const form = useChildForm(props.parent, props.index);
159+
return (
160+
<div>
161+
<FormInput form={form} type="text" name="name" />
162+
<FormInput form={form} type="number" name="amount" />
163+
<button type="button" onClick={() => props.remove(props.index)}>
164+
Remove
165+
</button>
166+
</div>
167+
);
168+
}
169+
```
170+
171+
## Fixed array example
172+
173+
A fixed array always has the same size, [`ChildForm`](https://github.com/CodeStix/typed-react-form/wiki/ChildForm) is used, and the index into the array is given using the name prop.
174+
175+
✔️ **Fixed array field containing strings**
176+
```jsx
177+
function AnswerForm() {
178+
const form = useForm({
179+
// Always 3 items in array
180+
answers: ["", "", ""]
181+
});
182+
return (
183+
<form
184+
onSubmit={(ev) => {
185+
ev.preventDefault();
186+
console.log("submit", form.values);
187+
}}
188+
>
189+
<ChildForm
190+
parent={form}
191+
name="answers"
192+
render={(form) => (
193+
<div>
194+
{/* Use array index as field name */}
195+
<p>Answer 1</p>
196+
<FormInput form={form} name={0} type="text" />
197+
<p>Answer 2</p>
198+
<FormInput form={form} name={1} type="text" />
199+
<p>Answer 3</p>
200+
<FormInput form={form} name={2} type="text" />
201+
</div>
202+
)}
203+
/>
204+
<button>Submit</button>
205+
</form>
206+
);
207+
}
208+
```
209+
210+
✔️ **Fixed array field containing objects**
211+
```jsx
212+
function SettingsForm() {
213+
const form = useForm({
214+
settings: [
215+
{ name: "Enable email", value: true },
216+
{ name: "Enable notifications", value: false }
217+
]
218+
});
219+
return (
220+
<form
221+
onSubmit={(ev) => {
222+
ev.preventDefault();
223+
console.log("submit", form.values);
224+
}}
225+
>
226+
<ChildForm // First child form is array
227+
parent={form}
228+
name="settings"
229+
render={(form) =>
230+
form.values.map((_, i) => (
231+
<ChildForm // Second child form is object in array
232+
key={i}
233+
parent={form}
234+
name={i}
235+
render={(form) => (
236+
<div>
237+
<p>{form.values.name}</p>
238+
<FormInput form={form} name="value" type="checkbox" />
239+
</div>
240+
)}
241+
/>
242+
))
243+
}
244+
/>
245+
<button>Submit</button>
246+
</form>
247+
);
248+
}
249+
```

articles/ArrayForm.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
A component that provides array manipulation functions and optimizations. This is a wrapper around [`useArrayForm`](https://github.com/CodeStix/typed-react-form/wiki/useArrayForm). The only difference is that this component does not render its content when the array is null/undefined ([is togglable](https://github.com/CodeStix/typed-react-form/wiki/Toggling-a-field)).
2+
3+
## Props
4+
5+
#### `form` **(required)**
6+
7+
The parent form which contains the array field to create a array child form for.
8+
9+
---
10+
11+
#### `name` **(required)**
12+
13+
The name of the array field in the parent form.
14+
15+
---
16+
17+
#### `render` **(required)**
18+
19+
A function that renders the array.
20+
21+
The render function provides an object parameter, containing the following fields:
22+
23+
- `form`: The child form associated with this array. Pass this to this child forms and input elements.
24+
- `values`: The array, you should `{map((e) => ...)}` this.
25+
- `setValues(values)`: A function to update all the array values at once.
26+
27+
**The object also contains helper functions to quickly manipulate the array field:**
28+
29+
- `remove(index)`: Function that removes a specific item at index in the array.
30+
- `clear()`: Function that clears the array.
31+
- `move(from, to)`: Function that moves an item in the array
32+
- `swap(index, newIndex)`: Function that swaps 2 items in the array.
33+
- `append(value)`: Function that appends an item to the end of the array.
34+
35+
## Usage
36+
37+
See [Array fields](https://github.com/CodeStix/typed-react-form/wiki/Array-fields).

articles/ChildForm.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
Use the `ChildForm` component if you want to make fields inside an object field available to inputs. This is a wrapper around [`useChildForm`](https://github.com/CodeStix/typed-react-form/wiki/useChildForm).
2+
3+
## Props
4+
5+
#### `form` (required)
6+
7+
The parent form which contains the object field to create a child form for.
8+
9+
---
10+
11+
#### `name` (required)
12+
13+
The name of the field in the parent form to create
14+
15+
---
16+
17+
#### `render` (required)
18+
19+
A function that renders, and creates inputs for the child form, which is passed as a parameter.
20+
21+
## Advanced
22+
23+
You can also use this component on array fields (index as name), but [`ArrayForm`](https://github.com/CodeStix/typed-react-form/wiki/ArrayForm) or [`useArrayForm`](https://github.com/CodeStix/typed-react-form/wiki/useArrayForm) is preferred when you want to create [dynamic array fields](https://github.com/CodeStix/typed-react-form/wiki/Array-fields). It provides useful array manipulation functions and optimizations.
24+
25+
This component does not render its content when the form is empty (happens when its parent field has been assigned `null`, `undefined` or `{}`).

0 commit comments

Comments
 (0)