Skip to content

Commit 91e4c3e

Browse files
authored
docs: documentation for v0.4 (#45)
1 parent 1de23e0 commit 91e4c3e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+1360
-1076
lines changed

README.md

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,29 @@
22

33
Conform is a form validation library built on top of the [Constraint Validation](https://caniuse.com/constraint-validation) API.
44

5-
- **Progressive Enhancement**: It is designed based on the [HTML specification](https://html.spec.whatwg.org/dev/form-control-infrastructure.html#the-constraint-validation-api). From validating the form to reporting error messages for each field, if you don't like part of the solution, just replace it with your own.
6-
- **Framework Agnostic**: The DOM is the only dependency. Conform makes use of native [Web APIs](https://developer.mozilla.org/en-US/docs/Web/API) exclusively. You don't have to use React / Vue / Svelte to utilise this library.
7-
- **Flexible Setup**: It can validates fields anywhere in the dom with the help of [form attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#form). Also enables CSS pseudo-classes like `:valid` and `:invalid`, allowing flexible styling across your form without the need to manipulate the class names.
5+
- **Progressive Enhancement**: Its APIs are designed with progressive enhancement in mind to ensure a smooth and resillent experience before javascript is ready.
6+
- **Server-first validation**: It simplifies the mental model by utilizing a server-first validation flow which submits your form for validation.
7+
- **Lightweight**: It is only [4kB](https://bundlephobia.com/package/@conform-to/react) compressed thanks to all the native [Web APIs](https://developer.mozilla.org/en-US/docs/Web/API). _#useThePlatform_
88

99
## Quick start
1010

11-
<!-- sandbox title="Simple demo" src="/examples/basic" -->
11+
<!-- sandbox src="/examples/basic" -->
1212

1313
```tsx
1414
import { useForm, useFieldset } from '@conform-to/react';
1515

1616
export default function LoginForm() {
1717
const form = useForm({
18-
onSubmit(event, { submission }) {
18+
onSubmit(event) {
1919
event.preventDefault();
2020

21-
console.log(submission);
21+
const formData = new FormData(event.currentTarget);
22+
const value = Object.fromEntries(formData);
23+
24+
console.log(value);
2225
},
2326
});
24-
const { email, password } = useFieldset(form.ref);
27+
const { email, password } = useFieldset(form.ref, form.config);
2528

2629
return (
2730
<form {...form.props}>
@@ -41,16 +44,6 @@ export default function LoginForm() {
4144
}
4245
```
4346

44-
Learn more about conform [here](https://conform.guide/basics)
47+
Learn more about conform [here](https://conform.guide/basics).
4548

4649
<!-- /sandbox -->
47-
48-
## API References
49-
50-
<!-- prettier-ignore-start -->
51-
| Package | Description | Size |
52-
| :------ | :---------- | :--- |
53-
| [@conform-to/react](packages/conform-react) | View adapter for [react](https://github.com/facebook/react) | [![package size](https://img.shields.io/bundlephobia/minzip/@conform-to/react)](https://bundlephobia.com/package/@conform-to/react) |
54-
| [@conform-to/yup](packages/conform-yup) | Schema resolver for [yup](https://github.com/jquense/yup) | [![package size](https://img.shields.io/bundlephobia/minzip/@conform-to/yup)](https://bundlephobia.com/package/@conform-to/yup) |
55-
| [@conform-to/zod](packages/conform-zod) | Schema resolver for [zod](https://github.com/colinhacks/zod) | [![package size](https://img.shields.io/bundlephobia/minzip/@conform-to/zod)](https://bundlephobia.com/package/@conform-to/zod) |
56-
<!-- prettier-ignore-end -->

docs/basics.md

Lines changed: 118 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
# Basics
22

3-
In this section, we will cover how to build a simple login form by utilizing native constraint and then enhancing it with conform.
3+
In this section, we will show you how to build a login form by utilizing the **Constraint Validation** API with **Conform**.
44

55
<!-- aside -->
66

77
## Table of Contents
88

99
- [Installation](#installation)
1010
- [Quick start](#quick-start)
11+
- [Constraint Validation](#constraint-validation)
1112
- [Capturing errors](#capturing-errors)
12-
- [Styling input](#styling-input)
13+
- [Customize messages](#customize-messages)
1314
- [Early reporting](#early-reporting)
1415
- [Demo](#demo)
1516

@@ -25,7 +26,7 @@ npm install @conform-to/react
2526

2627
To begin, let's make a login form with 2 basic requirements:
2728

28-
- The **email** field should be a valid email address
29+
- The **email** field should contain a valid email address
2930
- The **password** field should not be empty
3031

3132
```tsx
@@ -36,7 +37,8 @@ export default function LoginForm() {
3637
event.preventDefault();
3738

3839
const formData = new FormData(event.currentTarget);
39-
console.log(formData);
40+
41+
console.log(Object.fromEntries(formData));
4042
}}
4143
>
4244
<label>
@@ -59,77 +61,164 @@ export default function LoginForm() {
5961
}
6062
```
6163

62-
By utilising the [required](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/required) attribute, our form now stop users from submitting until they provide a valid email address with the password. We are also capturing the form value using the [FormData](https://developer.mozilla.org/en-US/docs/Web/API/FormData) API.
64+
Both the **email** input type and the [required](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/required) attribute are parts of the [Constraint Validation](#constraint-validation) API. It tells the browser to stop users from submitting the form until they provide a valid email address with the password.
65+
66+
### Constraint Validation
67+
68+
The [Constraint Validation](https://caniuse.com/constraint-validation) API is introduced with HTML5 to enable native client side form validation. This includes:
69+
70+
- Utilizing [HTML attributes](https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Constraint_validation#validation-related_attributes) for validations (e.g. `required`, `type`)
71+
- Accessing form validity and configuring custom constraint through the [DOM APIs](https://developer.mozilla.org/en-US/docs/Web/API/Constraint_validation#extensions_to_other_interfaces) (e.g `validityState`, `setCustomValidity()`)
72+
- Styling form elements with [CSS pseudo-class](https://developer.mozilla.org/en-US/docs/Learn/Forms/Form_validation#the_constraint_validation_api) based on the validity (e.g. `:required`, `:invalid`)
73+
74+
Conform utilizes these APIs internally. For example, form errors are reported by listening to the [invalid event](https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/invalid_event) and the error messages are captured from the element [validationMessage](https://developer.mozilla.org/en-US/docs/Web/API/HTMLObjectElement/validationMessage) property.
6375

6476
### Capturing errors
6577

66-
With the help of native form validation, users will see [error bubbles](https://codesandbox.io/s/cocky-fermi-zwjort?file=/src/App.js) popping up if they try to submit a form with invalid fields. These bubbles, unfortunately, are not customizable.
78+
With the help of Constraint Validation, users will see [error bubbles](https://codesandbox.io/s/cocky-fermi-zwjort?file=/src/App.js) popping up when they try to submit a form with invalid fields. These bubbles are not customizable unfortunately. What if we can capture the error messages and decide where to put them ourselves?
6779

68-
What if we can capture the error messages and decide where to put them ourselves? Let's introduce the [useForm](/packages/conform-react/README.md#useform) and [useFieldset](/packages/conform-react/README.md#usefieldset) hooks:
80+
Let's introduce the [useForm](/packages/conform-react/README.md#useform) and [useFieldset](/packages/conform-react/README.md#usefieldset) hooks.
6981

7082
```tsx
7183
import { useForm, useFieldset } from '@conform-to/react';
7284

7385
export default function LoginForm() {
7486
/**
7587
* The useForm hook let you take control of the browser
76-
* validation flow and customize it
88+
* validation flow and customize it. The submit event
89+
* handler will be called only when the form is valid.
7790
*/
7891
const form = useForm({
7992
onSubmit(event, { formData }) {
8093
event.preventDefault();
8194

82-
console.log(formData);
95+
console.log(Object.fromEntries(formData));
8396
},
8497
});
98+
8599
/**
86-
* The useFieldset hook let you subscribe to the state
87-
* of each field
100+
* The useFieldset hook helps you configure each field and
101+
* subscribe to its state. The properties accessed should
102+
* match the name of the inputs.
88103
*/
89-
const { email, password } = useFieldset(form.ref);
104+
const { email, password } = useFieldset(form.ref, form.config);
90105

91106
return (
92107
<form {...form.props}>
93-
{/* ... */}
108+
<label>
109+
<div>Email</div>
110+
<input type="email" name="email" required autoComplete="off" />
111+
{/* The email error captured */}
112+
<div>{email.error}</div>
113+
</label>
114+
<label>
115+
<div>Password</div>
116+
<input type="password" name="password" required />
117+
{/* The password error captured */}
118+
<div>{password.error}</div>
119+
</label>
120+
<label>
121+
<div>
122+
<span>Remember me</span>
123+
<input type="checkbox" name="remember-me" value="yes" />
124+
</div>
125+
</label>
94126
<button type="submit">Login</button>
95127
</form>
96128
);
97129
}
98130
```
99131

100-
<details>
101-
<summary>Where are these error messages come from?</summary>
102-
You might already notice - they are the same as the one you saw on the error bubbles: Indeed, these messages are provided by the browser vendor and might varies depending on your operating system and user language setting.
103-
</details>
132+
### Customize messages
133+
134+
Although we haven't define any error messages yet, the form above should be able to populate some message depends on the conditions. These messages are provided by the browser vendor and might vary depending on your users operating system and language setting. Let's customize messages based on the elements' [ValidityState](https://developer.mozilla.org/en-US/docs/Web/API/ValidityState).
135+
136+
```tsx
137+
import { useForm, parse, getFormElements } from '@conform-to/react';
104138

105-
### Styling input
139+
export default function LoginForm() {
140+
const form = useForm({
141+
onValidate({ form, formData }) {
142+
/**
143+
* By parsing the formData, you will be able to access:
144+
* 1) The value in the defined structure
145+
* e.g. { email: '', password: '' }
146+
* 2) The error found while parsing the form data
147+
* e.g. [ ['email', 'Email is required'], ... ]
148+
* 3) The type and intent of the submission
149+
*
150+
* More details will be covered in the submission section
151+
*/
152+
const submission = parse(formData);
153+
154+
/**
155+
* The `getFormElements` returns all input/select/textarea/button
156+
* elements in the form
157+
*/
158+
for (const element of getFormElements(form)) {
159+
switch (element.name) {
160+
case 'email': {
161+
if (element.validity.valueMissing) {
162+
/**
163+
* This will be true when the input is marked as `required`
164+
* while the input is blank
165+
*/
166+
submission.error.push([element.name, 'Email is required']);
167+
} else if (element.validity.typeMismatch) {
168+
/**
169+
* This will be true when the input type is `email`
170+
* while the value does not match
171+
*/
172+
submission.error.push([element.name, 'Email is invalid']);
173+
} else if (!element.value.endsWith('gmail.com')) {
174+
/**
175+
* You can also validate the field manually with custom logic
176+
*/
177+
submission.error.push([element.name, 'Only gmail is accepted']);
178+
}
179+
break;
180+
}
181+
case 'password': {
182+
if (element.validity.valueMissing) {
183+
submission.error.push([element.name, 'Password is required']);
184+
}
185+
break;
186+
}
187+
}
188+
}
189+
190+
return submission;
191+
},
106192

107-
It might be common to update the class name based on the error state. However, conform makes it possible to style using a combination of [CSS pseudo-class](https://developer.mozilla.org/en-US/docs/Learn/Forms/Form_validation#the_constraint_validation_api) with data attribute as well:
193+
// ....
194+
});
108195

109-
```css
110-
input[data-conform-touched]:invalid {
111-
border-color: red;
196+
// ...
112197
}
113198
```
114199

115200
### Early reporting
116201

117-
Currently, form error will not be reported until a submission is made. If you want it to be shown earlier, just set the `initialReport` option to `onBlur` and now error should be reported once the user leave the field:
202+
Currently, form error is reported only when a submission is made. If you want it to be shown earlier, you can set the `initialReport` option to `onBlur` and then error will be reported once the user leave the field.
118203

119204
```tsx
120205
import { useForm } from '@conform-to/react';
121206

122207
export default function LoginForm() {
123208
const form = useForm({
209+
/**
210+
* Define when the error should be reported initially.
211+
* Support "onSubmit", "onChange", "onBlur".
212+
*
213+
* Default to `onSubmit`.
214+
*/
124215
initialReport: 'onBlur',
216+
onSubmit(event, { formData }) {
217+
// ...
218+
},
125219
});
126220

127-
return (
128-
<form {...form.props}>
129-
{/* ... */}
130-
<button type="submit">Login</button>
131-
</form>
132-
);
221+
// ...
133222
}
134223
```
135224

0 commit comments

Comments
 (0)