@conform-to/react 0.4.0-pre.1 → 0.4.0-pre.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +186 -77
- package/hooks.d.ts +5 -5
- package/hooks.js +46 -32
- package/index.d.ts +1 -1
- package/index.js +4 -4
- package/module/hooks.js +47 -33
- package/module/index.js +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -10,8 +10,12 @@
|
|
|
10
10
|
- [useFieldset](#usefieldset)
|
|
11
11
|
- [useFieldList](#usefieldlist)
|
|
12
12
|
- [useControlledInput](#usecontrolledinput)
|
|
13
|
-
- [createValidate](#createvalidate)
|
|
14
13
|
- [conform](#conform)
|
|
14
|
+
- [hasError](#haserror)
|
|
15
|
+
- [isFieldElement](#isfieldelement)
|
|
16
|
+
- [parse](#parse)
|
|
17
|
+
- [setFormError](#setformerror)
|
|
18
|
+
- [shouldValidate](#shouldvalidate)
|
|
15
19
|
|
|
16
20
|
<!-- /aside -->
|
|
17
21
|
|
|
@@ -21,15 +25,23 @@ By default, the browser calls the [reportValidity()](https://developer.mozilla.o
|
|
|
21
25
|
|
|
22
26
|
This hook enhances the form validation behaviour in 3 parts:
|
|
23
27
|
|
|
24
|
-
1. It
|
|
25
|
-
2. It
|
|
28
|
+
1. It enhances form validation with custom rules by subscribing to different DOM events and reporting the errors only when it is configured to do so.
|
|
29
|
+
2. It unifies client and server validation in one place.
|
|
26
30
|
3. It exposes the state of each field in the form of [data attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/data-*), such as `data-conform-touched`, allowing flexible styling across your form without the need to manipulate the class names.
|
|
27
31
|
|
|
28
32
|
```tsx
|
|
29
33
|
import { useForm } from '@conform-to/react';
|
|
30
34
|
|
|
31
35
|
function LoginForm() {
|
|
32
|
-
const
|
|
36
|
+
const form = useForm({
|
|
37
|
+
/**
|
|
38
|
+
* Validation mode.
|
|
39
|
+
* Support "client-only" or "server-validation".
|
|
40
|
+
*
|
|
41
|
+
* Default to `client-only`.
|
|
42
|
+
*/
|
|
43
|
+
mode: 'client-only',
|
|
44
|
+
|
|
33
45
|
/**
|
|
34
46
|
* Define when the error should be reported initially.
|
|
35
47
|
* Support "onSubmit", "onChange", "onBlur".
|
|
@@ -38,6 +50,16 @@ function LoginForm() {
|
|
|
38
50
|
*/
|
|
39
51
|
initialReport: 'onBlur',
|
|
40
52
|
|
|
53
|
+
/**
|
|
54
|
+
* An object representing the initial value of the form.
|
|
55
|
+
*/
|
|
56
|
+
defaultValue: undefined;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* An object describing the state from the last submission
|
|
60
|
+
*/
|
|
61
|
+
state: undefined;
|
|
62
|
+
|
|
41
63
|
/**
|
|
42
64
|
* Enable native validation before hydation.
|
|
43
65
|
*
|
|
@@ -54,43 +76,38 @@ function LoginForm() {
|
|
|
54
76
|
|
|
55
77
|
/**
|
|
56
78
|
* A function to be called when the form should be (re)validated.
|
|
79
|
+
* Only sync validation is supported
|
|
57
80
|
*/
|
|
58
|
-
|
|
81
|
+
onValidate({ form, formData, submission }) {
|
|
59
82
|
// ...
|
|
60
83
|
},
|
|
61
84
|
|
|
62
85
|
/**
|
|
63
86
|
* The submit event handler of the form.
|
|
64
87
|
*/
|
|
65
|
-
onSubmit(event) {
|
|
88
|
+
onSubmit(event, { form, formData, submission }) {
|
|
66
89
|
// ...
|
|
67
90
|
},
|
|
68
91
|
});
|
|
69
92
|
|
|
70
|
-
|
|
71
|
-
<form {...formProps}>
|
|
72
|
-
<input type="email" name="email" required />
|
|
73
|
-
<input type="password" name="password" required />
|
|
74
|
-
<button type="submit">Login</button>
|
|
75
|
-
</form>
|
|
76
|
-
);
|
|
93
|
+
// ...
|
|
77
94
|
}
|
|
78
95
|
```
|
|
79
96
|
|
|
80
97
|
<details>
|
|
81
|
-
<summary>What is `
|
|
98
|
+
<summary>What is `form.props`?</summary>
|
|
82
99
|
|
|
83
100
|
It is a group of properties properties required to hook into form events. They can also be set explicitly as shown below:
|
|
84
101
|
|
|
85
102
|
```tsx
|
|
86
103
|
function RandomForm() {
|
|
87
|
-
const
|
|
104
|
+
const form = useForm();
|
|
88
105
|
|
|
89
106
|
return (
|
|
90
107
|
<form
|
|
91
|
-
ref={
|
|
92
|
-
onSubmit={
|
|
93
|
-
noValidate={
|
|
108
|
+
ref={form.props.ref}
|
|
109
|
+
onSubmit={form.props.onSubmit}
|
|
110
|
+
noValidate={form.props.noValidate}
|
|
94
111
|
>
|
|
95
112
|
{/* ... */}
|
|
96
113
|
</form>
|
|
@@ -103,17 +120,17 @@ function RandomForm() {
|
|
|
103
120
|
<details>
|
|
104
121
|
<summary>Does it work with custom form component like Remix Form?</summary>
|
|
105
122
|
|
|
106
|
-
Yes! It will fallback to native form submission
|
|
123
|
+
Yes! It will fallback to native form submission as long as the submit event is not default prevented.
|
|
107
124
|
|
|
108
125
|
```tsx
|
|
109
126
|
import { useFrom } from '@conform-to/react';
|
|
110
127
|
import { Form } from '@remix-run/react';
|
|
111
128
|
|
|
112
129
|
function LoginForm() {
|
|
113
|
-
const
|
|
130
|
+
const form = useForm();
|
|
114
131
|
|
|
115
132
|
return (
|
|
116
|
-
<Form method="post" action="/login" {...
|
|
133
|
+
<Form method="post" action="/login" {...form.props}>
|
|
117
134
|
{/* ... */}
|
|
118
135
|
</Form>
|
|
119
136
|
);
|
|
@@ -123,9 +140,9 @@ function LoginForm() {
|
|
|
123
140
|
</details>
|
|
124
141
|
|
|
125
142
|
<details>
|
|
126
|
-
<summary>Is the `
|
|
143
|
+
<summary>Is the `onValidate` function required?</summary>
|
|
127
144
|
|
|
128
|
-
The `
|
|
145
|
+
The `onValidate` function is not required if the validation logic can be fully covered by the [native constraints](https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Constraint_validation#validation-related_attributes), e.g. **required** / **min** / **pattern** etc.
|
|
129
146
|
|
|
130
147
|
```tsx
|
|
131
148
|
import { useForm, useFieldset } from '@conform-to/react';
|
|
@@ -156,10 +173,10 @@ function LoginForm() {
|
|
|
156
173
|
|
|
157
174
|
### useFieldset
|
|
158
175
|
|
|
159
|
-
This hook can be used to monitor the state of each field and help
|
|
176
|
+
This hook can be used to monitor the state of each field and help configuration. It lets you:
|
|
160
177
|
|
|
161
178
|
1. Capturing errors at the form/fieldset level, removing the need to setup invalid handler on each field.
|
|
162
|
-
2. Defining config in one central place. e.g. name, default value and constraint, then distributing it to each field
|
|
179
|
+
2. Defining config in one central place. e.g. name, default value and constraint, then distributing it to each field with the [conform](#conform) helpers.
|
|
163
180
|
|
|
164
181
|
```tsx
|
|
165
182
|
import { useForm, useFieldset } from '@conform-to/react';
|
|
@@ -493,58 +510,7 @@ function MuiForm() {
|
|
|
493
510
|
<MenuItem value="c">Category C</MenuItem>
|
|
494
511
|
</TextField>
|
|
495
512
|
</fieldset>
|
|
496
|
-
)
|
|
497
|
-
}
|
|
498
|
-
```
|
|
499
|
-
|
|
500
|
-
---
|
|
501
|
-
|
|
502
|
-
### createValidate
|
|
503
|
-
|
|
504
|
-
This help you configure a validate function to check the validity of each fields and setup custom messages using the Constraint Validation APIs.
|
|
505
|
-
|
|
506
|
-
```tsx
|
|
507
|
-
import { useForm, createValidate } from '@conform-to/react';
|
|
508
|
-
|
|
509
|
-
export default function SignupForm() {
|
|
510
|
-
const formProps = useForm({
|
|
511
|
-
validate: createValidate((field, formData) => {
|
|
512
|
-
switch (field.name) {
|
|
513
|
-
case 'email':
|
|
514
|
-
if (field.validity.valueMissing) {
|
|
515
|
-
field.setCustomValidity('Email is required');
|
|
516
|
-
} else if (field.validity.typeMismatch) {
|
|
517
|
-
field.setCustomValidity('Please enter a valid email');
|
|
518
|
-
} else {
|
|
519
|
-
field.setCustomValidity('');
|
|
520
|
-
}
|
|
521
|
-
break;
|
|
522
|
-
case 'password':
|
|
523
|
-
if (field.validity.valueMissing) {
|
|
524
|
-
field.setCustomValidity('Password is required');
|
|
525
|
-
} else if (field.validity.tooShort) {
|
|
526
|
-
field.setCustomValidity(
|
|
527
|
-
'The password should be at least 10 characters long',
|
|
528
|
-
);
|
|
529
|
-
} else {
|
|
530
|
-
field.setCustomValidity('');
|
|
531
|
-
}
|
|
532
|
-
break;
|
|
533
|
-
case 'confirm-password': {
|
|
534
|
-
if (field.validity.valueMissing) {
|
|
535
|
-
field.setCustomValidity('Confirm Password is required');
|
|
536
|
-
} else if (field.value !== formData.get('password')) {
|
|
537
|
-
field.setCustomValidity('The password does not match');
|
|
538
|
-
} else {
|
|
539
|
-
field.setCustomValidity('');
|
|
540
|
-
}
|
|
541
|
-
break;
|
|
542
|
-
}
|
|
543
|
-
}
|
|
544
|
-
}),
|
|
545
|
-
});
|
|
546
|
-
|
|
547
|
-
return <form {...formProps}>{/* ... */}</form>;
|
|
513
|
+
);
|
|
548
514
|
}
|
|
549
515
|
```
|
|
550
516
|
|
|
@@ -615,3 +581,146 @@ function RandomForm() {
|
|
|
615
581
|
);
|
|
616
582
|
}
|
|
617
583
|
```
|
|
584
|
+
|
|
585
|
+
### hasError
|
|
586
|
+
|
|
587
|
+
This helper checks if there is any message defined in error array with the provided name.
|
|
588
|
+
|
|
589
|
+
```ts
|
|
590
|
+
import { hasError } from '@conform-to/react';
|
|
591
|
+
|
|
592
|
+
/**
|
|
593
|
+
* Assume the error looks like this:
|
|
594
|
+
*/
|
|
595
|
+
const error = [['email', 'Email is required']];
|
|
596
|
+
|
|
597
|
+
// This will log `true`
|
|
598
|
+
console.log(hasError(error, 'email'));
|
|
599
|
+
|
|
600
|
+
// This will log `false`
|
|
601
|
+
console.log(hasError(error, 'password'));
|
|
602
|
+
```
|
|
603
|
+
|
|
604
|
+
---
|
|
605
|
+
|
|
606
|
+
### isFieldElement
|
|
607
|
+
|
|
608
|
+
This checks if the provided element is an `input` / `select` / `textarea` or `button` HTML element with type guard. Useful when you need to access the validityState of the fields and modify the validation message manually.
|
|
609
|
+
|
|
610
|
+
```tsx
|
|
611
|
+
import { isFieldElement } from '@conform-to/react';
|
|
612
|
+
|
|
613
|
+
export default function SignupForm() {
|
|
614
|
+
const form = useForm({
|
|
615
|
+
onValidate({ form }) {
|
|
616
|
+
for (const element of form.elements) {
|
|
617
|
+
if (isFieldElement(element)) {
|
|
618
|
+
switch (field.name) {
|
|
619
|
+
case 'email':
|
|
620
|
+
if (field.validity.valueMissing) {
|
|
621
|
+
field.setCustomValidity('Email is required');
|
|
622
|
+
} else if (field.validity.typeMismatch) {
|
|
623
|
+
field.setCustomValidity('Please enter a valid email');
|
|
624
|
+
} else {
|
|
625
|
+
field.setCustomValidity('');
|
|
626
|
+
}
|
|
627
|
+
break;
|
|
628
|
+
case 'password':
|
|
629
|
+
if (field.validity.valueMissing) {
|
|
630
|
+
field.setCustomValidity('Password is required');
|
|
631
|
+
} else if (field.validity.tooShort) {
|
|
632
|
+
field.setCustomValidity(
|
|
633
|
+
'The password should be at least 10 characters long',
|
|
634
|
+
);
|
|
635
|
+
} else {
|
|
636
|
+
field.setCustomValidity('');
|
|
637
|
+
}
|
|
638
|
+
break;
|
|
639
|
+
case 'confirm-password': {
|
|
640
|
+
if (field.validity.valueMissing) {
|
|
641
|
+
field.setCustomValidity('Confirm Password is required');
|
|
642
|
+
} else if (field.value !== formData.get('password')) {
|
|
643
|
+
field.setCustomValidity('The password does not match');
|
|
644
|
+
} else {
|
|
645
|
+
field.setCustomValidity('');
|
|
646
|
+
}
|
|
647
|
+
break;
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
},
|
|
653
|
+
});
|
|
654
|
+
|
|
655
|
+
// ...
|
|
656
|
+
}
|
|
657
|
+
```
|
|
658
|
+
|
|
659
|
+
---
|
|
660
|
+
|
|
661
|
+
### parse
|
|
662
|
+
|
|
663
|
+
It parses the formData based on the [naming convention](/docs/submission).
|
|
664
|
+
|
|
665
|
+
```tsx
|
|
666
|
+
import { parse } from '@conform-to/react';
|
|
667
|
+
|
|
668
|
+
const formData = new FormData(formElement);
|
|
669
|
+
const submission = parse(formData);
|
|
670
|
+
|
|
671
|
+
console.log(submission);
|
|
672
|
+
```
|
|
673
|
+
|
|
674
|
+
---
|
|
675
|
+
|
|
676
|
+
### setFormError
|
|
677
|
+
|
|
678
|
+
This helpers updates the form error based on the submission result by looping through all elements in the form and update the error with the [setCustomValidity](https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/setCustomValidity) API.
|
|
679
|
+
|
|
680
|
+
```tsx
|
|
681
|
+
import { setFormError } from '@conform-to/react';
|
|
682
|
+
|
|
683
|
+
function ExampleForm() {
|
|
684
|
+
const form = useForm({
|
|
685
|
+
onValidate({ form, submission }) {
|
|
686
|
+
const error = validate(submission);
|
|
687
|
+
|
|
688
|
+
setFormError(form, {
|
|
689
|
+
...submission,
|
|
690
|
+
error,
|
|
691
|
+
});
|
|
692
|
+
},
|
|
693
|
+
});
|
|
694
|
+
|
|
695
|
+
// ...
|
|
696
|
+
}
|
|
697
|
+
```
|
|
698
|
+
|
|
699
|
+
---
|
|
700
|
+
|
|
701
|
+
### shouldValidate
|
|
702
|
+
|
|
703
|
+
This helper checks if the scope of validation includes a specific field by checking the submission:
|
|
704
|
+
|
|
705
|
+
```tsx
|
|
706
|
+
import { shouldValidate } from '@conform-to/react';
|
|
707
|
+
|
|
708
|
+
/**
|
|
709
|
+
* The submission type and metadata give us hint on what should be valdiated.
|
|
710
|
+
* If the type is 'validate', only the field with name matching the metadata must be validated.
|
|
711
|
+
*
|
|
712
|
+
* However, if the type is `undefined`, both will log true (Default submission)
|
|
713
|
+
*/
|
|
714
|
+
const submission = {
|
|
715
|
+
type: 'validate',
|
|
716
|
+
metadata: 'email',
|
|
717
|
+
value: {},
|
|
718
|
+
error: [],
|
|
719
|
+
};
|
|
720
|
+
|
|
721
|
+
// This will log 'true'
|
|
722
|
+
console.log(shouldValidate(submission, 'email'));
|
|
723
|
+
|
|
724
|
+
// This will log 'false'
|
|
725
|
+
console.log(shouldValidate(submission, 'password'));
|
|
726
|
+
```
|
package/hooks.d.ts
CHANGED
|
@@ -40,7 +40,7 @@ export interface FormConfig<Schema extends Record<string, any>> {
|
|
|
40
40
|
/**
|
|
41
41
|
* A function to be called when the form should be (re)validated.
|
|
42
42
|
*/
|
|
43
|
-
onValidate?: (context: FormContext<Schema>) =>
|
|
43
|
+
onValidate?: (context: FormContext<Schema>) => Array<[string, string]>;
|
|
44
44
|
/**
|
|
45
45
|
* The submit event handler of the form. It will be called
|
|
46
46
|
* only when the form is considered valid.
|
|
@@ -65,7 +65,7 @@ interface Form<Schema extends Record<string, any>> {
|
|
|
65
65
|
* Returns properties required to hook into form events.
|
|
66
66
|
* Applied custom validation and define when error should be reported.
|
|
67
67
|
*
|
|
68
|
-
* @see https://github.com/edmundhung/conform/tree/v0.4.0-pre.
|
|
68
|
+
* @see https://github.com/edmundhung/conform/tree/v0.4.0-pre.2/packages/conform-react/README.md#useform
|
|
69
69
|
*/
|
|
70
70
|
export declare function useForm<Schema extends Record<string, any>>(config?: FormConfig<Schema>): Form<Schema>;
|
|
71
71
|
/**
|
|
@@ -106,7 +106,7 @@ export interface FieldsetConfig<Schema extends Record<string, any>> {
|
|
|
106
106
|
/**
|
|
107
107
|
* Returns all the information about the fieldset.
|
|
108
108
|
*
|
|
109
|
-
* @see https://github.com/edmundhung/conform/tree/v0.4.0-pre.
|
|
109
|
+
* @see https://github.com/edmundhung/conform/tree/v0.4.0-pre.2/packages/conform-react/README.md#usefieldset
|
|
110
110
|
*/
|
|
111
111
|
export declare function useFieldset<Schema extends Record<string, any>>(ref: RefObject<HTMLFormElement | HTMLFieldSetElement>, config?: FieldsetConfig<Schema>): Fieldset<Schema>;
|
|
112
112
|
export declare function useFieldset<Schema extends Record<string, any>>(ref: RefObject<HTMLFormElement | HTMLFieldSetElement>, config?: FieldConfig<Schema>): Fieldset<Schema>;
|
|
@@ -133,7 +133,7 @@ interface ListControl<Schema> {
|
|
|
133
133
|
* Returns a list of key and config, with a group of helpers
|
|
134
134
|
* configuring buttons for list manipulation
|
|
135
135
|
*
|
|
136
|
-
* @see https://github.com/edmundhung/conform/tree/v0.4.0-pre.
|
|
136
|
+
* @see https://github.com/edmundhung/conform/tree/v0.4.0-pre.2/packages/conform-react/README.md#usefieldlist
|
|
137
137
|
*/
|
|
138
138
|
export declare function useFieldList<Payload = any>(ref: RefObject<HTMLFormElement | HTMLFieldSetElement>, config: FieldConfig<Array<Payload>>): [
|
|
139
139
|
Array<{
|
|
@@ -163,7 +163,7 @@ interface InputControl<Element extends {
|
|
|
163
163
|
* This is particular useful when integrating dropdown and datepicker whichs
|
|
164
164
|
* introduces custom input mode.
|
|
165
165
|
*
|
|
166
|
-
* @see https://github.com/edmundhung/conform/tree/v0.4.0-pre.
|
|
166
|
+
* @see https://github.com/edmundhung/conform/tree/v0.4.0-pre.2/packages/conform-react/README.md#usecontrolledinput
|
|
167
167
|
*/
|
|
168
168
|
export declare function useControlledInput<Element extends {
|
|
169
169
|
focus: () => void;
|
package/hooks.js
CHANGED
|
@@ -11,7 +11,7 @@ var helpers = require('./helpers.js');
|
|
|
11
11
|
* Returns properties required to hook into form events.
|
|
12
12
|
* Applied custom validation and define when error should be reported.
|
|
13
13
|
*
|
|
14
|
-
* @see https://github.com/edmundhung/conform/tree/v0.4.0-pre.
|
|
14
|
+
* @see https://github.com/edmundhung/conform/tree/v0.4.0-pre.2/packages/conform-react/README.md#useform
|
|
15
15
|
*/
|
|
16
16
|
function useForm() {
|
|
17
17
|
var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
@@ -182,48 +182,62 @@ function useForm() {
|
|
|
182
182
|
return;
|
|
183
183
|
}
|
|
184
184
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
185
|
+
try {
|
|
186
|
+
var formData = dom.getFormData(form, submitter);
|
|
187
|
+
var submission = dom.parse(formData);
|
|
188
|
+
var _context = {
|
|
189
|
+
form,
|
|
190
|
+
formData,
|
|
191
|
+
submission
|
|
192
|
+
}; // Touch all fields only if the submitter is not a command button
|
|
193
|
+
|
|
194
|
+
if (submission.context === 'submit') {
|
|
195
|
+
for (var field of form.elements) {
|
|
196
|
+
if (dom.isFieldElement(field)) {
|
|
197
|
+
// Mark the field as touched
|
|
198
|
+
field.dataset.conformTouched = 'true';
|
|
199
|
+
}
|
|
198
200
|
}
|
|
199
201
|
}
|
|
200
|
-
}
|
|
201
202
|
|
|
202
|
-
|
|
203
|
-
if (!config.noValidate && !submitter.formNoValidate) {
|
|
204
|
-
var _config$onValidate;
|
|
203
|
+
var _error;
|
|
205
204
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
205
|
+
if (typeof config.onValidate === 'function') {
|
|
206
|
+
_error = config.onValidate(_context);
|
|
207
|
+
} else {
|
|
208
|
+
if (config.mode !== 'server-validation') {
|
|
209
|
+
// Clear previous result
|
|
210
|
+
dom.setFormError(form, {
|
|
211
|
+
context: 'submit',
|
|
212
|
+
value: {},
|
|
213
|
+
error: []
|
|
214
|
+
});
|
|
211
215
|
}
|
|
216
|
+
|
|
217
|
+
_error = dom.getFormError(form);
|
|
212
218
|
}
|
|
213
|
-
|
|
214
|
-
if (
|
|
215
|
-
|
|
219
|
+
|
|
220
|
+
if (_error.length > 0) {
|
|
221
|
+
submission.error.push(..._error);
|
|
216
222
|
}
|
|
217
|
-
}
|
|
218
223
|
|
|
219
|
-
|
|
220
|
-
if (config.mode !== 'server-validation' && submission.type === 'validate') {
|
|
224
|
+
if (!config.noValidate && !submitter.formNoValidate && dom.hasError(submission.error) || submission.context === 'validate' && config.mode !== 'server-validation') {
|
|
221
225
|
event.preventDefault();
|
|
222
226
|
} else {
|
|
223
227
|
var _config$onSubmit;
|
|
224
228
|
|
|
225
|
-
(_config$onSubmit = config.onSubmit) === null || _config$onSubmit === void 0 ? void 0 : _config$onSubmit.call(config, event,
|
|
229
|
+
(_config$onSubmit = config.onSubmit) === null || _config$onSubmit === void 0 ? void 0 : _config$onSubmit.call(config, event, _context);
|
|
226
230
|
}
|
|
231
|
+
|
|
232
|
+
if (event.defaultPrevented) {
|
|
233
|
+
dom.setFormError(form, submission);
|
|
234
|
+
|
|
235
|
+
if (!form.reportValidity()) {
|
|
236
|
+
dom.focusFirstInvalidField(form);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
} catch (e) {
|
|
240
|
+
console.warn(e);
|
|
227
241
|
}
|
|
228
242
|
}
|
|
229
243
|
|
|
@@ -423,7 +437,7 @@ function useFieldset(ref, config) {
|
|
|
423
437
|
* Returns a list of key and config, with a group of helpers
|
|
424
438
|
* configuring buttons for list manipulation
|
|
425
439
|
*
|
|
426
|
-
* @see https://github.com/edmundhung/conform/tree/v0.4.0-pre.
|
|
440
|
+
* @see https://github.com/edmundhung/conform/tree/v0.4.0-pre.2/packages/conform-react/README.md#usefieldlist
|
|
427
441
|
*/
|
|
428
442
|
function useFieldList(ref, config) {
|
|
429
443
|
var configRef = react.useRef(config);
|
|
@@ -567,7 +581,7 @@ function useFieldList(ref, config) {
|
|
|
567
581
|
* This is particular useful when integrating dropdown and datepicker whichs
|
|
568
582
|
* introduces custom input mode.
|
|
569
583
|
*
|
|
570
|
-
* @see https://github.com/edmundhung/conform/tree/v0.4.0-pre.
|
|
584
|
+
* @see https://github.com/edmundhung/conform/tree/v0.4.0-pre.2/packages/conform-react/README.md#usecontrolledinput
|
|
571
585
|
*/
|
|
572
586
|
function useControlledInput(config) {
|
|
573
587
|
var _config$defaultValue4;
|
package/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { type FieldsetConstraint, type Submission, hasError, isFieldElement, parse,
|
|
1
|
+
export { type FieldsetConstraint, type Submission, getFormError, hasError, isFieldElement, parse, shouldValidate, } from '@conform-to/dom';
|
|
2
2
|
export * from './hooks';
|
|
3
3
|
export * as conform from './helpers';
|
package/index.js
CHANGED
|
@@ -8,6 +8,10 @@ var helpers = require('./helpers.js');
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
|
|
11
|
+
Object.defineProperty(exports, 'getFormError', {
|
|
12
|
+
enumerable: true,
|
|
13
|
+
get: function () { return dom.getFormError; }
|
|
14
|
+
});
|
|
11
15
|
Object.defineProperty(exports, 'hasError', {
|
|
12
16
|
enumerable: true,
|
|
13
17
|
get: function () { return dom.hasError; }
|
|
@@ -20,10 +24,6 @@ Object.defineProperty(exports, 'parse', {
|
|
|
20
24
|
enumerable: true,
|
|
21
25
|
get: function () { return dom.parse; }
|
|
22
26
|
});
|
|
23
|
-
Object.defineProperty(exports, 'setFormError', {
|
|
24
|
-
enumerable: true,
|
|
25
|
-
get: function () { return dom.setFormError; }
|
|
26
|
-
});
|
|
27
27
|
Object.defineProperty(exports, 'shouldValidate', {
|
|
28
28
|
enumerable: true,
|
|
29
29
|
get: function () { return dom.shouldValidate; }
|
package/module/hooks.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { objectSpread2 as _objectSpread2 } from './_virtual/_rollupPluginBabelHelpers.js';
|
|
2
|
-
import { getSubmissionType, setFormError, focusFirstInvalidField, requestSubmit, isFieldElement, getFormData, parse, getPaths, getName, requestValidate, getFormElement, parseListCommand, updateList } from '@conform-to/dom';
|
|
2
|
+
import { getSubmissionType, setFormError, focusFirstInvalidField, requestSubmit, isFieldElement, getFormData, parse, getFormError, hasError, getPaths, getName, requestValidate, getFormElement, parseListCommand, updateList } from '@conform-to/dom';
|
|
3
3
|
import { useRef, useState, useEffect } from 'react';
|
|
4
4
|
import { input } from './helpers.js';
|
|
5
5
|
|
|
@@ -7,7 +7,7 @@ import { input } from './helpers.js';
|
|
|
7
7
|
* Returns properties required to hook into form events.
|
|
8
8
|
* Applied custom validation and define when error should be reported.
|
|
9
9
|
*
|
|
10
|
-
* @see https://github.com/edmundhung/conform/tree/v0.4.0-pre.
|
|
10
|
+
* @see https://github.com/edmundhung/conform/tree/v0.4.0-pre.2/packages/conform-react/README.md#useform
|
|
11
11
|
*/
|
|
12
12
|
function useForm() {
|
|
13
13
|
var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
@@ -178,48 +178,62 @@ function useForm() {
|
|
|
178
178
|
return;
|
|
179
179
|
}
|
|
180
180
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
181
|
+
try {
|
|
182
|
+
var formData = getFormData(form, submitter);
|
|
183
|
+
var submission = parse(formData);
|
|
184
|
+
var _context = {
|
|
185
|
+
form,
|
|
186
|
+
formData,
|
|
187
|
+
submission
|
|
188
|
+
}; // Touch all fields only if the submitter is not a command button
|
|
189
|
+
|
|
190
|
+
if (submission.context === 'submit') {
|
|
191
|
+
for (var field of form.elements) {
|
|
192
|
+
if (isFieldElement(field)) {
|
|
193
|
+
// Mark the field as touched
|
|
194
|
+
field.dataset.conformTouched = 'true';
|
|
195
|
+
}
|
|
194
196
|
}
|
|
195
197
|
}
|
|
196
|
-
}
|
|
197
198
|
|
|
198
|
-
|
|
199
|
-
if (!config.noValidate && !submitter.formNoValidate) {
|
|
200
|
-
var _config$onValidate;
|
|
199
|
+
var _error;
|
|
201
200
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
201
|
+
if (typeof config.onValidate === 'function') {
|
|
202
|
+
_error = config.onValidate(_context);
|
|
203
|
+
} else {
|
|
204
|
+
if (config.mode !== 'server-validation') {
|
|
205
|
+
// Clear previous result
|
|
206
|
+
setFormError(form, {
|
|
207
|
+
context: 'submit',
|
|
208
|
+
value: {},
|
|
209
|
+
error: []
|
|
210
|
+
});
|
|
207
211
|
}
|
|
212
|
+
|
|
213
|
+
_error = getFormError(form);
|
|
208
214
|
}
|
|
209
|
-
|
|
210
|
-
if (
|
|
211
|
-
|
|
215
|
+
|
|
216
|
+
if (_error.length > 0) {
|
|
217
|
+
submission.error.push(..._error);
|
|
212
218
|
}
|
|
213
|
-
}
|
|
214
219
|
|
|
215
|
-
|
|
216
|
-
if (config.mode !== 'server-validation' && submission.type === 'validate') {
|
|
220
|
+
if (!config.noValidate && !submitter.formNoValidate && hasError(submission.error) || submission.context === 'validate' && config.mode !== 'server-validation') {
|
|
217
221
|
event.preventDefault();
|
|
218
222
|
} else {
|
|
219
223
|
var _config$onSubmit;
|
|
220
224
|
|
|
221
|
-
(_config$onSubmit = config.onSubmit) === null || _config$onSubmit === void 0 ? void 0 : _config$onSubmit.call(config, event,
|
|
225
|
+
(_config$onSubmit = config.onSubmit) === null || _config$onSubmit === void 0 ? void 0 : _config$onSubmit.call(config, event, _context);
|
|
222
226
|
}
|
|
227
|
+
|
|
228
|
+
if (event.defaultPrevented) {
|
|
229
|
+
setFormError(form, submission);
|
|
230
|
+
|
|
231
|
+
if (!form.reportValidity()) {
|
|
232
|
+
focusFirstInvalidField(form);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
} catch (e) {
|
|
236
|
+
console.warn(e);
|
|
223
237
|
}
|
|
224
238
|
}
|
|
225
239
|
|
|
@@ -419,7 +433,7 @@ function useFieldset(ref, config) {
|
|
|
419
433
|
* Returns a list of key and config, with a group of helpers
|
|
420
434
|
* configuring buttons for list manipulation
|
|
421
435
|
*
|
|
422
|
-
* @see https://github.com/edmundhung/conform/tree/v0.4.0-pre.
|
|
436
|
+
* @see https://github.com/edmundhung/conform/tree/v0.4.0-pre.2/packages/conform-react/README.md#usefieldlist
|
|
423
437
|
*/
|
|
424
438
|
function useFieldList(ref, config) {
|
|
425
439
|
var configRef = useRef(config);
|
|
@@ -563,7 +577,7 @@ function useFieldList(ref, config) {
|
|
|
563
577
|
* This is particular useful when integrating dropdown and datepicker whichs
|
|
564
578
|
* introduces custom input mode.
|
|
565
579
|
*
|
|
566
|
-
* @see https://github.com/edmundhung/conform/tree/v0.4.0-pre.
|
|
580
|
+
* @see https://github.com/edmundhung/conform/tree/v0.4.0-pre.2/packages/conform-react/README.md#usecontrolledinput
|
|
567
581
|
*/
|
|
568
582
|
function useControlledInput(config) {
|
|
569
583
|
var _config$defaultValue4;
|
package/module/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { hasError, isFieldElement, parse,
|
|
1
|
+
export { getFormError, hasError, isFieldElement, parse, shouldValidate } from '@conform-to/dom';
|
|
2
2
|
export { useControlledInput, useFieldList, useFieldset, useForm } from './hooks.js';
|
|
3
3
|
import * as helpers from './helpers.js';
|
|
4
4
|
export { helpers as conform };
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@conform-to/react",
|
|
3
3
|
"description": "Conform view adapter for react",
|
|
4
4
|
"license": "MIT",
|
|
5
|
-
"version": "0.4.0-pre.
|
|
5
|
+
"version": "0.4.0-pre.2",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"module": "module/index.js",
|
|
8
8
|
"repository": {
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"url": "https://github.com/edmundhung/conform/issues"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@conform-to/dom": "0.4.0-pre.
|
|
22
|
+
"@conform-to/dom": "0.4.0-pre.2"
|
|
23
23
|
},
|
|
24
24
|
"peerDependencies": {
|
|
25
25
|
"react": ">=16.8"
|