You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+11-18Lines changed: 11 additions & 18 deletions
Original file line number
Diff line number
Diff line change
@@ -2,26 +2,29 @@
2
2
3
3
Conform is a form validation library built on top of the [Constraint Validation](https://caniuse.com/constraint-validation) API.
4
4
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_
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**.
4
4
5
5
<!-- aside -->
6
6
7
7
## Table of Contents
8
8
9
9
-[Installation](#installation)
10
10
-[Quick start](#quick-start)
11
+
-[Constraint Validation](#constraint-validation)
11
12
-[Capturing errors](#capturing-errors)
12
-
-[Styling input](#styling-input)
13
+
-[Customize messages](#customize-messages)
13
14
-[Early reporting](#early-reporting)
14
15
-[Demo](#demo)
15
16
@@ -25,7 +26,7 @@ npm install @conform-to/react
25
26
26
27
To begin, let's make a login form with 2 basic requirements:
27
28
28
-
- The **email** field should be a valid email address
29
+
- The **email** field should contain a valid email address
29
30
- The **password** field should not be empty
30
31
31
32
```tsx
@@ -36,7 +37,8 @@ export default function LoginForm() {
36
37
event.preventDefault();
37
38
38
39
const formData =newFormData(event.currentTarget);
39
-
console.log(formData);
40
+
41
+
console.log(Object.fromEntries(formData));
40
42
}}
41
43
>
42
44
<label>
@@ -59,77 +61,164 @@ export default function LoginForm() {
59
61
}
60
62
```
61
63
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.
63
75
64
76
### Capturing errors
65
77
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 bubblesare not customizable unfortunately. What if we can capture the error messages and decide where to put them ourselves?
67
79
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.
<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).
* 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 ofgetFormElements(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
+
} elseif (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
+
} elseif (!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
+
returnsubmission;
191
+
},
106
192
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
+
});
108
195
109
-
```css
110
-
input[data-conform-touched]:invalid {
111
-
border-color: red;
196
+
// ...
112
197
}
113
198
```
114
199
115
200
### Early reporting
116
201
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.
118
203
119
204
```tsx
120
205
import { useForm } from'@conform-to/react';
121
206
122
207
exportdefaultfunction LoginForm() {
123
208
const form =useForm({
209
+
/**
210
+
* Define when the error should be reported initially.
0 commit comments