@digigov/form 0.8.4 → 0.8.5-alpha
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/Field/utils.js +1 -0
- package/FieldArray/FieldArray.stories.playwright.json +168 -0
- package/FieldArray/__stories__/Default.js +3 -5
- package/FieldArray/__stories__/WithExactLength.js +3 -5
- package/FieldArray/index.js +1 -0
- package/FieldObject/index.js +1 -2
- package/{FormBuilder.d.ts → FormBuilder/FormBuilder.d.ts} +0 -0
- package/{FormBuilder.js → FormBuilder/FormBuilder.js} +0 -0
- package/FormBuilder/FormBuilder.mdx +271 -0
- package/FormBuilder/FormBuilder.stories.d.ts +7 -0
- package/FormBuilder/FormBuilder.stories.js +30 -0
- package/FormBuilder/__stories__/Default.d.ts +2 -0
- package/FormBuilder/__stories__/Default.js +45 -0
- package/FormBuilder/index.d.ts +2 -0
- package/FormBuilder/index.js +11 -0
- package/MultiplicityField/MultiplicityField.mdx +148 -0
- package/MultiplicityField/__stories__/Default.js +3 -5
- package/MultiplicityField/__stories__/WithExactLength.js +3 -5
- package/MultiplicityField/__stories__/WithMaxLength.js +3 -5
- package/MultiplicityField/__stories__/WithMinAndMaxLength.js +3 -5
- package/MultiplicityField/__stories__/WithMinLength.js +3 -5
- package/Questions/Step/StepArrayReview.js +2 -2
- package/Questions/__snapshots__/index.spec.tsx.snap +649 -449
- package/Questions/index.mdx +0 -187
- package/create-simple-form.mdx +515 -0
- package/es/Field/utils.js +1 -0
- package/es/FieldArray/FieldArray.stories.playwright.json +168 -0
- package/es/FieldArray/__stories__/Default.js +3 -5
- package/es/FieldArray/__stories__/WithExactLength.js +3 -5
- package/es/FieldArray/index.js +1 -0
- package/es/FieldObject/index.js +1 -2
- package/es/{FormBuilder.js → FormBuilder/FormBuilder.js} +0 -0
- package/es/FormBuilder/FormBuilder.mdx +271 -0
- package/es/FormBuilder/FormBuilder.stories.js +6 -0
- package/es/FormBuilder/__stories__/Default.js +25 -0
- package/es/FormBuilder/index.js +2 -0
- package/es/MultiplicityField/MultiplicityField.mdx +148 -0
- package/es/MultiplicityField/__stories__/Default.js +3 -5
- package/es/MultiplicityField/__stories__/WithExactLength.js +3 -5
- package/es/MultiplicityField/__stories__/WithMaxLength.js +3 -5
- package/es/MultiplicityField/__stories__/WithMinAndMaxLength.js +3 -5
- package/es/MultiplicityField/__stories__/WithMinLength.js +3 -5
- package/es/Questions/Step/StepArrayReview.js +1 -1
- package/es/Questions/__snapshots__/index.spec.tsx.snap +649 -449
- package/es/Questions/index.mdx +0 -187
- package/es/create-simple-form.mdx +515 -0
- package/es/index.mdx +37 -199
- package/es/inputs/Checkboxes/Checkboxes.stories.js +6 -0
- package/es/inputs/Checkboxes/__stories__/Default.js +43 -0
- package/es/inputs/DateInput/DateInput.stories.js +6 -0
- package/es/inputs/DateInput/__stories__/Default.js +44 -0
- package/es/inputs/Input/Input.stories.js +13 -0
- package/es/inputs/Input/__stories__/AFM.js +25 -0
- package/es/inputs/Input/__stories__/Boolean.js +26 -0
- package/es/inputs/Input/__stories__/Default.js +26 -0
- package/es/inputs/Input/__stories__/IBAN.js +26 -0
- package/es/inputs/Input/__stories__/Integer.js +26 -0
- package/es/inputs/Input/__stories__/MobilePhone.js +25 -0
- package/es/inputs/Input/__stories__/PhoneNumber.js +25 -0
- package/es/inputs/Input/__stories__/PostalCode.js +28 -0
- package/es/inputs/Input/index.mdx +0 -2
- package/es/inputs/Label/Label.stories.js +6 -0
- package/es/inputs/Label/__stories__/Default.js +30 -0
- package/es/inputs/Radio/Radio.stories.js +6 -0
- package/es/inputs/Radio/__stories__/Default.js +48 -0
- package/es/inputs/Select/Select.stories.js +6 -0
- package/es/inputs/Select/__stories__/Default.js +54 -0
- package/es/installation.mdx +72 -0
- package/es/registry.js +129 -0
- package/esm/Field/utils.js +1 -0
- package/esm/FieldArray/FieldArray.stories.playwright.json +168 -0
- package/esm/FieldArray/__stories__/Default.js +3 -5
- package/esm/FieldArray/__stories__/WithExactLength.js +3 -5
- package/esm/FieldArray/index.js +1 -0
- package/esm/FieldObject/index.js +1 -2
- package/esm/{FormBuilder.js → FormBuilder/FormBuilder.js} +0 -0
- package/esm/FormBuilder/FormBuilder.mdx +271 -0
- package/esm/FormBuilder/FormBuilder.stories.js +6 -0
- package/esm/FormBuilder/__stories__/Default.js +25 -0
- package/esm/FormBuilder/index.js +2 -0
- package/esm/MultiplicityField/MultiplicityField.mdx +148 -0
- package/esm/MultiplicityField/__stories__/Default.js +3 -5
- package/esm/MultiplicityField/__stories__/WithExactLength.js +3 -5
- package/esm/MultiplicityField/__stories__/WithMaxLength.js +3 -5
- package/esm/MultiplicityField/__stories__/WithMinAndMaxLength.js +3 -5
- package/esm/MultiplicityField/__stories__/WithMinLength.js +3 -5
- package/esm/Questions/Step/StepArrayReview.js +1 -1
- package/esm/Questions/__snapshots__/index.spec.tsx.snap +649 -449
- package/esm/Questions/index.mdx +0 -187
- package/esm/create-simple-form.mdx +515 -0
- package/esm/index.js +1 -1
- package/esm/index.mdx +37 -199
- package/esm/inputs/Checkboxes/Checkboxes.stories.js +6 -0
- package/esm/inputs/Checkboxes/__stories__/Default.js +43 -0
- package/esm/inputs/DateInput/DateInput.stories.js +6 -0
- package/esm/inputs/DateInput/__stories__/Default.js +44 -0
- package/esm/inputs/Input/Input.stories.js +13 -0
- package/esm/inputs/Input/__stories__/AFM.js +25 -0
- package/esm/inputs/Input/__stories__/Boolean.js +26 -0
- package/esm/inputs/Input/__stories__/Default.js +26 -0
- package/esm/inputs/Input/__stories__/IBAN.js +26 -0
- package/esm/inputs/Input/__stories__/Integer.js +26 -0
- package/esm/inputs/Input/__stories__/MobilePhone.js +25 -0
- package/esm/inputs/Input/__stories__/PhoneNumber.js +25 -0
- package/esm/inputs/Input/__stories__/PostalCode.js +28 -0
- package/esm/inputs/Input/index.mdx +0 -2
- package/esm/inputs/Label/Label.stories.js +6 -0
- package/esm/inputs/Label/__stories__/Default.js +30 -0
- package/esm/inputs/Radio/Radio.stories.js +6 -0
- package/esm/inputs/Radio/__stories__/Default.js +48 -0
- package/esm/inputs/Select/Select.stories.js +6 -0
- package/esm/inputs/Select/__stories__/Default.js +54 -0
- package/esm/installation.mdx +72 -0
- package/esm/registry.js +129 -0
- package/index.mdx +37 -199
- package/inputs/Checkboxes/Checkboxes.stories.d.ts +7 -0
- package/inputs/Checkboxes/Checkboxes.stories.js +30 -0
- package/inputs/Checkboxes/__stories__/Default.d.ts +2 -0
- package/inputs/Checkboxes/__stories__/Default.js +63 -0
- package/inputs/DateInput/DateInput.stories.d.ts +7 -0
- package/inputs/DateInput/DateInput.stories.js +30 -0
- package/inputs/DateInput/__stories__/Default.d.ts +2 -0
- package/inputs/DateInput/__stories__/Default.js +64 -0
- package/inputs/Input/Input.stories.d.ts +14 -0
- package/inputs/Input/Input.stories.js +128 -0
- package/inputs/Input/__stories__/AFM.d.ts +2 -0
- package/inputs/Input/__stories__/AFM.js +45 -0
- package/inputs/Input/__stories__/Boolean.d.ts +2 -0
- package/inputs/Input/__stories__/Boolean.js +46 -0
- package/inputs/Input/__stories__/Default.d.ts +2 -0
- package/inputs/Input/__stories__/Default.js +46 -0
- package/inputs/Input/__stories__/IBAN.d.ts +2 -0
- package/inputs/Input/__stories__/IBAN.js +46 -0
- package/inputs/Input/__stories__/Integer.d.ts +2 -0
- package/inputs/Input/__stories__/Integer.js +46 -0
- package/inputs/Input/__stories__/MobilePhone.d.ts +2 -0
- package/inputs/Input/__stories__/MobilePhone.js +45 -0
- package/inputs/Input/__stories__/PhoneNumber.d.ts +2 -0
- package/inputs/Input/__stories__/PhoneNumber.js +45 -0
- package/inputs/Input/__stories__/PostalCode.d.ts +2 -0
- package/inputs/Input/__stories__/PostalCode.js +48 -0
- package/inputs/Input/index.mdx +0 -2
- package/inputs/Label/Label.stories.d.ts +7 -0
- package/inputs/Label/Label.stories.js +30 -0
- package/inputs/Label/__stories__/Default.d.ts +2 -0
- package/inputs/Label/__stories__/Default.js +50 -0
- package/inputs/Radio/Radio.stories.d.ts +7 -0
- package/inputs/Radio/Radio.stories.js +30 -0
- package/inputs/Radio/__stories__/Default.d.ts +2 -0
- package/inputs/Radio/__stories__/Default.js +68 -0
- package/inputs/Select/Select.stories.d.ts +7 -0
- package/inputs/Select/Select.stories.js +30 -0
- package/inputs/Select/__stories__/Default.d.ts +2 -0
- package/inputs/Select/__stories__/Default.js +74 -0
- package/installation.mdx +72 -0
- package/package.json +6 -6
- package/registry.d.ts +59 -0
- package/registry.js +198 -0
- package/types.d.ts +1 -1
package/Questions/index.mdx
CHANGED
|
@@ -3,198 +3,11 @@ title: Questions
|
|
|
3
3
|
parent: docs/ui/components
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
import Questions, {
|
|
7
|
-
Step,
|
|
8
|
-
StepForm,
|
|
9
|
-
StepQuote,
|
|
10
|
-
StepTitle,
|
|
11
|
-
} from '@digigov/form/Questions';
|
|
12
|
-
import { Field } from '@digigov/form';
|
|
13
|
-
const steps = [
|
|
14
|
-
{
|
|
15
|
-
name: 'intro',
|
|
16
|
-
caption: 'intro.caption',
|
|
17
|
-
title: 'intro.title',
|
|
18
|
-
description: 'intro.description',
|
|
19
|
-
fields: [
|
|
20
|
-
{
|
|
21
|
-
key: 'name',
|
|
22
|
-
label: {
|
|
23
|
-
primary: 'name.field.primary',
|
|
24
|
-
secondary: 'name.field.secondary',
|
|
25
|
-
},
|
|
26
|
-
required: true,
|
|
27
|
-
type: 'string',
|
|
28
|
-
},
|
|
29
|
-
],
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
name: 'time',
|
|
33
|
-
nextStep: (data) => {
|
|
34
|
-
if (data.time.age < 26) {
|
|
35
|
-
return 'review';
|
|
36
|
-
}
|
|
37
|
-
},
|
|
38
|
-
caption: 'time.caption',
|
|
39
|
-
title: 'time.title',
|
|
40
|
-
description: 'time.description',
|
|
41
|
-
fields: [
|
|
42
|
-
{
|
|
43
|
-
key: 'age',
|
|
44
|
-
label: {
|
|
45
|
-
primary: 'age.field.primary',
|
|
46
|
-
secondary: 'age.field.secondary',
|
|
47
|
-
},
|
|
48
|
-
required: true,
|
|
49
|
-
type: 'int',
|
|
50
|
-
},
|
|
51
|
-
],
|
|
52
|
-
},
|
|
53
|
-
{
|
|
54
|
-
name: 'boomer',
|
|
55
|
-
show: (data) => {
|
|
56
|
-
return data.time.age >= 56;
|
|
57
|
-
},
|
|
58
|
-
caption: 'boomer.caption',
|
|
59
|
-
title: 'boomer.title',
|
|
60
|
-
description: 'boomer.description',
|
|
61
|
-
fields: [
|
|
62
|
-
{
|
|
63
|
-
key: 'adult',
|
|
64
|
-
label: {
|
|
65
|
-
primary: 'adult.field.primary',
|
|
66
|
-
secondary: 'adult.field.secondary',
|
|
67
|
-
},
|
|
68
|
-
required: true,
|
|
69
|
-
type: 'string',
|
|
70
|
-
},
|
|
71
|
-
],
|
|
72
|
-
},
|
|
73
|
-
{
|
|
74
|
-
name: 'genx',
|
|
75
|
-
show: (data) => {
|
|
76
|
-
return data.time.age >= 41 && data.time.age < 56;
|
|
77
|
-
},
|
|
78
|
-
caption: 'genx.caption',
|
|
79
|
-
title: 'genx.title',
|
|
80
|
-
description: 'genx.description',
|
|
81
|
-
fields: [
|
|
82
|
-
{
|
|
83
|
-
key: 'adult',
|
|
84
|
-
label: {
|
|
85
|
-
primary: 'adult.field.primary',
|
|
86
|
-
secondary: 'adult.field.secondary',
|
|
87
|
-
},
|
|
88
|
-
required: true,
|
|
89
|
-
type: 'string',
|
|
90
|
-
},
|
|
91
|
-
],
|
|
92
|
-
},
|
|
93
|
-
{
|
|
94
|
-
name: 'millenial',
|
|
95
|
-
show: (data) => {
|
|
96
|
-
return data.time.age >= 26 && data.time.age < 41;
|
|
97
|
-
},
|
|
98
|
-
caption: 'millenial.caption',
|
|
99
|
-
title: 'millenial.title',
|
|
100
|
-
description: 'millenial.description',
|
|
101
|
-
fields: [
|
|
102
|
-
{
|
|
103
|
-
key: 'adult',
|
|
104
|
-
label: {
|
|
105
|
-
primary: 'adult.field.primary',
|
|
106
|
-
secondary: 'adult.field.secondary',
|
|
107
|
-
},
|
|
108
|
-
required: true,
|
|
109
|
-
type: 'string',
|
|
110
|
-
},
|
|
111
|
-
],
|
|
112
|
-
},
|
|
113
|
-
{
|
|
114
|
-
name: 'generic',
|
|
115
|
-
caption: 'generic.caption',
|
|
116
|
-
title: 'generic.title',
|
|
117
|
-
description: 'generic.description',
|
|
118
|
-
fields: [
|
|
119
|
-
{
|
|
120
|
-
key: 'info',
|
|
121
|
-
label: {
|
|
122
|
-
primary: 'info.field.primary',
|
|
123
|
-
secondary: 'info.field.secondary',
|
|
124
|
-
},
|
|
125
|
-
required: true,
|
|
126
|
-
type: 'string',
|
|
127
|
-
},
|
|
128
|
-
],
|
|
129
|
-
},
|
|
130
|
-
];
|
|
131
|
-
|
|
132
6
|
## Example
|
|
133
7
|
|
|
134
|
-
<Questions
|
|
135
|
-
steps={steps}
|
|
136
|
-
onActiveStep={(step) => {
|
|
137
|
-
console.log(step);
|
|
138
|
-
}}
|
|
139
|
-
initialData={{ intro: { name: 'Νίκος Παπαδόπουλος' }, time: { age: 33 } }}
|
|
140
|
-
initialStep={steps[0]}
|
|
141
|
-
onChange={(data) => {
|
|
142
|
-
console.log(data);
|
|
143
|
-
}}
|
|
144
|
-
onSubmit={(data) => {
|
|
145
|
-
console.log(data, 'submit');
|
|
146
|
-
}}
|
|
147
|
-
>
|
|
148
|
-
<Step name="intro">
|
|
149
|
-
<StepTitle />
|
|
150
|
-
<StepQuote>This is the intro</StepQuote>
|
|
151
|
-
<StepForm submitButton={true}>
|
|
152
|
-
<Field name="name" />
|
|
153
|
-
</StepForm>
|
|
154
|
-
</Step>
|
|
155
|
-
<Step name="time">
|
|
156
|
-
<StepTitle />
|
|
157
|
-
<StepQuote>This is the age</StepQuote>
|
|
158
|
-
<StepForm submitButton={true}>
|
|
159
|
-
<Field name="age" />
|
|
160
|
-
</StepForm>
|
|
161
|
-
</Step>
|
|
162
|
-
<Step name="boomer">
|
|
163
|
-
<StepTitle />
|
|
164
|
-
<StepQuote>This is the conditioned step </StepQuote>
|
|
165
|
-
<StepForm submitButton={true}>
|
|
166
|
-
<Field name="adult" />
|
|
167
|
-
</StepForm>
|
|
168
|
-
</Step>
|
|
169
|
-
<Step name="genx">
|
|
170
|
-
<StepTitle />
|
|
171
|
-
<StepQuote>This is the conditioned step </StepQuote>
|
|
172
|
-
<StepForm submitButton={true}>
|
|
173
|
-
<Field name="adult" />
|
|
174
|
-
</StepForm>
|
|
175
|
-
</Step>
|
|
176
|
-
<Step name="millenial">
|
|
177
|
-
<StepTitle />
|
|
178
|
-
<StepQuote>This is the conditioned step </StepQuote>
|
|
179
|
-
<StepForm submitButton={true}>
|
|
180
|
-
<Field name="adult" />
|
|
181
|
-
</StepForm>
|
|
182
|
-
</Step>
|
|
183
|
-
<Step name="generic">
|
|
184
|
-
<StepTitle />
|
|
185
|
-
<StepQuote>This is a normal step </StepQuote>
|
|
186
|
-
<StepForm submitButton={true}>
|
|
187
|
-
<Field name="info" />
|
|
188
|
-
</StepForm>
|
|
189
|
-
</Step>
|
|
190
|
-
</Questions>
|
|
191
8
|
|
|
192
9
|
## API
|
|
193
10
|
|
|
194
11
|
### Properties
|
|
195
12
|
|
|
196
|
-
<PropsDoc data={Questions.__doc__} />
|
|
197
|
-
|
|
198
13
|
### Styles
|
|
199
|
-
|
|
200
|
-
<StylesDoc data={Questions.__doc__} />
|
|
@@ -0,0 +1,515 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: create-simple-form
|
|
3
|
+
title: Create a simple Digigov Form
|
|
4
|
+
sidebar_label: Creating simple forms
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
import LeadText from "@site/src/components/LeadText";
|
|
8
|
+
|
|
9
|
+
<LeadText>This guide walks through building a simple form page, complete with
|
|
10
|
+
validation and data serialisation.</LeadText>
|
|
11
|
+
|
|
12
|
+
## What we are building
|
|
13
|
+
|
|
14
|
+
Before we start diving into more advanced usecases, let's first create a form
|
|
15
|
+
asking users for their personal information.
|
|
16
|
+
|
|
17
|
+
* First name
|
|
18
|
+
* Last name
|
|
19
|
+
* AFM (Greek tax number)
|
|
20
|
+
* Telephone number
|
|
21
|
+
* Marital status
|
|
22
|
+
|
|
23
|
+
As you can see, this form is pretty basic. But even for a basic form like this
|
|
24
|
+
we want to implement features that will help our users submit their data. We
|
|
25
|
+
should add basic input validations and get any data from those inputs, assuming
|
|
26
|
+
that these validation checks passed. These features are not rocket science, but
|
|
27
|
+
even though they are used all the time, there is a lot of boilerplate code that
|
|
28
|
+
can be abstracted away.
|
|
29
|
+
|
|
30
|
+
Let's see how Digigov Form helps us build forms in no time.
|
|
31
|
+
|
|
32
|
+
## Create your first form component
|
|
33
|
+
|
|
34
|
+
Let's start by creating a form in plain HTML. In this example, the first element
|
|
35
|
+
we use is a `<form>` followed by `<label>` and `<input>` elements. These are
|
|
36
|
+
primitive elements.
|
|
37
|
+
|
|
38
|
+
```jsx
|
|
39
|
+
import React from 'react';
|
|
40
|
+
|
|
41
|
+
export default function SimpleForm() {
|
|
42
|
+
return <form>
|
|
43
|
+
<label>
|
|
44
|
+
Name:
|
|
45
|
+
<input type="text" name="name" />
|
|
46
|
+
</label>
|
|
47
|
+
<input type="submit" value="Submit" />
|
|
48
|
+
</form>
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
In Digigov Form, we use the same primitive elements under the hood but we add a
|
|
53
|
+
lot of built-in functionality. Let's take a quick look on how we can transform
|
|
54
|
+
the same form using Digigov Form.
|
|
55
|
+
|
|
56
|
+
The default export of `@digigov/form` package is a React component that can be
|
|
57
|
+
used for wrapping Field components. The component is the same as
|
|
58
|
+
`@digigov/form/FormBuilder` and it can be used in two distinct ways. We will
|
|
59
|
+
talk about that in a more advanced guide.
|
|
60
|
+
|
|
61
|
+
```jsx
|
|
62
|
+
import React from 'react';
|
|
63
|
+
// highlight-next-line
|
|
64
|
+
import Form from '@digigov/form';
|
|
65
|
+
|
|
66
|
+
export default function SimpleForm() {
|
|
67
|
+
// highlight-start
|
|
68
|
+
return <Form>
|
|
69
|
+
{/* this is where the fields are going to be placed */}
|
|
70
|
+
</Form>
|
|
71
|
+
// highlight-end
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Adding the first field
|
|
76
|
+
|
|
77
|
+
In this state, the form is just an empty shell waiting for us to define its
|
|
78
|
+
fields. According to our initial requirements set in the beginning of this
|
|
79
|
+
guide, we should create a new field with label ‘First name‘.
|
|
80
|
+
|
|
81
|
+
Let's go ahead and import the `Field` component and use it to render an input
|
|
82
|
+
field and a label. This component creates and manages any necessary React
|
|
83
|
+
components transparently. All you need to do is describe a few React props.
|
|
84
|
+
|
|
85
|
+
* `key`
|
|
86
|
+
* `name`
|
|
87
|
+
* `type`
|
|
88
|
+
* `label`
|
|
89
|
+
* `required`
|
|
90
|
+
|
|
91
|
+
These props can be then passed down the `Field` component which will be rendered
|
|
92
|
+
by `FormBuilder`.
|
|
93
|
+
|
|
94
|
+
Take a look at this live example. You can also use the live editor to play
|
|
95
|
+
around with the example code.
|
|
96
|
+
|
|
97
|
+
```jsx
|
|
98
|
+
import React from 'react';
|
|
99
|
+
// highlight-next-line
|
|
100
|
+
import Form, { Field } from '@digigov/form';
|
|
101
|
+
|
|
102
|
+
export default function SimpleForm() {
|
|
103
|
+
return <Form>
|
|
104
|
+
// highlight-start
|
|
105
|
+
<Field
|
|
106
|
+
key="firstName"
|
|
107
|
+
name="firstName"
|
|
108
|
+
label={{ primary: "First name" }}
|
|
109
|
+
type="string"
|
|
110
|
+
required
|
|
111
|
+
/>
|
|
112
|
+
// highlight-end
|
|
113
|
+
</Form>
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Hooray! 🎉
|
|
118
|
+
|
|
119
|
+
It looks like the first two fields of our awesome form are working as
|
|
120
|
+
expected. They are pretty basic, string inputs, accepting data input but they
|
|
121
|
+
don't seem to submit data or do any validation in their current state.
|
|
122
|
+
|
|
123
|
+
```jsx live
|
|
124
|
+
import React from 'react';
|
|
125
|
+
import Form, { Field } from '@digigov/form';
|
|
126
|
+
|
|
127
|
+
export default function SimpleForm() {
|
|
128
|
+
return <Form>
|
|
129
|
+
<Field
|
|
130
|
+
key="firstName"
|
|
131
|
+
name="firstName"
|
|
132
|
+
label={{ primary: "First name" }}
|
|
133
|
+
type="string"
|
|
134
|
+
required
|
|
135
|
+
/>
|
|
136
|
+
<Field
|
|
137
|
+
key="lastName"
|
|
138
|
+
name="lastName"
|
|
139
|
+
label={{ primary: "Last name" }}
|
|
140
|
+
type="string"
|
|
141
|
+
required
|
|
142
|
+
/>
|
|
143
|
+
</Form>
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Adding a submit button
|
|
148
|
+
|
|
149
|
+
Before we proceed with adding the rest of the fields, we should first make sure
|
|
150
|
+
that the form is working, validating and submitting data.
|
|
151
|
+
|
|
152
|
+
Let's modify the previous example and use a `@digigov/ui/form/Button` to submit
|
|
153
|
+
data. First we should import the button component and use it right at the
|
|
154
|
+
bottom of our form.
|
|
155
|
+
|
|
156
|
+
It is important to note that you should make sure the Button has a
|
|
157
|
+
`type="submit"` prop. In any other case, the button will not exhibit the correct
|
|
158
|
+
behaviour when users try to submit data using their keyboard (eg. hitting the
|
|
159
|
+
enter key) or using any other tools eg. screen readers.
|
|
160
|
+
|
|
161
|
+
```jsx
|
|
162
|
+
import React from 'react';
|
|
163
|
+
import Form, { Field } from '@digigov/form';
|
|
164
|
+
// highlight-next-line
|
|
165
|
+
import Button from '@digigov/ui/core/Button';
|
|
166
|
+
|
|
167
|
+
export default function SimpleForm() {
|
|
168
|
+
return <Form>
|
|
169
|
+
{/* this is where the fields are going to be placed */}
|
|
170
|
+
<Field
|
|
171
|
+
key="firstName"
|
|
172
|
+
name="firstName"
|
|
173
|
+
label={{ primary: "First name" }}
|
|
174
|
+
type="string"
|
|
175
|
+
required
|
|
176
|
+
/>
|
|
177
|
+
<Field
|
|
178
|
+
key="lastName"
|
|
179
|
+
name="lastName"
|
|
180
|
+
label={{ primary: "Last name" }}
|
|
181
|
+
type="string"
|
|
182
|
+
required
|
|
183
|
+
/>
|
|
184
|
+
// highlight-next-line
|
|
185
|
+
<Button type="submit">Continue</Button>
|
|
186
|
+
</Form>
|
|
187
|
+
}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
The code now looks fine. You can go ahead and test that the fields are
|
|
191
|
+
validating as we have instructed them. The form should display red errors when
|
|
192
|
+
you try to submit it with empty values.
|
|
193
|
+
|
|
194
|
+
Go ahead and try it in the live example below. You can also remove the
|
|
195
|
+
`required` prop from one of the fields in the live editor, and see how that
|
|
196
|
+
affects the submit behaviour.
|
|
197
|
+
|
|
198
|
+
```jsx live
|
|
199
|
+
import React from 'react';
|
|
200
|
+
import Form, { Field } from '@digigov/form';
|
|
201
|
+
import Button from '@digigov/ui/core/Button';
|
|
202
|
+
|
|
203
|
+
export default function SimpleForm() {
|
|
204
|
+
return <Form>
|
|
205
|
+
{/* this is where the fields are going to be placed */}
|
|
206
|
+
<Field
|
|
207
|
+
key="firstName"
|
|
208
|
+
name="firstName"
|
|
209
|
+
label={{ primary: "First name" }}
|
|
210
|
+
type="string"
|
|
211
|
+
required
|
|
212
|
+
/>
|
|
213
|
+
<Field
|
|
214
|
+
key="lastName"
|
|
215
|
+
name="lastName"
|
|
216
|
+
label={{ primary: "Last name" }}
|
|
217
|
+
type="string"
|
|
218
|
+
required
|
|
219
|
+
/>
|
|
220
|
+
<Button type="submit">Continue</Button>
|
|
221
|
+
</Form>
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Straightaway, the form is actually doing something and it is validating our
|
|
226
|
+
inputs with almost zero coding needed.
|
|
227
|
+
|
|
228
|
+
That's good. But we have yet to gather data in our code when users submit the form.
|
|
229
|
+
|
|
230
|
+
## Handling onSubmit events
|
|
231
|
+
|
|
232
|
+
Naturally, when we get data from HTML forms, we make use of the `submit` events
|
|
233
|
+
that are bubbling up. In React, we follow the convention of naming event
|
|
234
|
+
handlers like `onChange` and `onSubmit`.
|
|
235
|
+
|
|
236
|
+
We use the same familiar pattern as many other libraries. We get data inside an
|
|
237
|
+
event handler function and we can render this information in our application or
|
|
238
|
+
choose to send it to a remote server via an API.
|
|
239
|
+
|
|
240
|
+
In our case, we need a quick and dirty way to display the actual values we have
|
|
241
|
+
just entered to a form right back to us and render them for debugging purposes.
|
|
242
|
+
|
|
243
|
+
We will use the `useState` hook inside our functional component. This will let
|
|
244
|
+
us react to a `submit` event and locally save the form data as key-value pairs
|
|
245
|
+
in our state. Then we can call `JSON.stringify` and render the raw JSON
|
|
246
|
+
information.
|
|
247
|
+
|
|
248
|
+
```jsx
|
|
249
|
+
// highlight-next-line
|
|
250
|
+
import React, { useState } from 'react';
|
|
251
|
+
import Form, { Field } from '@digigov/form';
|
|
252
|
+
import Button from '@digigov/ui/core/Button';
|
|
253
|
+
|
|
254
|
+
export default function SimpleForm() {
|
|
255
|
+
// highlight-start
|
|
256
|
+
const [submittedData, setSubmittedData] = useState({})
|
|
257
|
+
const handleSubmit = (data) => {
|
|
258
|
+
setSubmittedData(data);
|
|
259
|
+
}
|
|
260
|
+
return <>
|
|
261
|
+
<Form onSubmit={handleSubmit}>
|
|
262
|
+
// highlight-end
|
|
263
|
+
{/* this is where the fields are going to be placed */}
|
|
264
|
+
<Field
|
|
265
|
+
key="firstName"
|
|
266
|
+
name="firstName"
|
|
267
|
+
label={{ primary: "First name" }}
|
|
268
|
+
type="string"
|
|
269
|
+
required
|
|
270
|
+
/>
|
|
271
|
+
<Field
|
|
272
|
+
key="lastName"
|
|
273
|
+
name="lastName"
|
|
274
|
+
label={{ primary: "Last name" }}
|
|
275
|
+
type="string"
|
|
276
|
+
required
|
|
277
|
+
/>
|
|
278
|
+
<Button type="submit">Continue</Button>
|
|
279
|
+
</Form>
|
|
280
|
+
// highlight-start
|
|
281
|
+
{<>
|
|
282
|
+
You submitted the following values
|
|
283
|
+
<pre><code>
|
|
284
|
+
{JSON.stringify(submittedData)}
|
|
285
|
+
</code></pre>
|
|
286
|
+
</>}
|
|
287
|
+
// highlight-end
|
|
288
|
+
</>
|
|
289
|
+
}
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
As you can see in the live example when the form first loads, the submitted data
|
|
293
|
+
is an empty object, which is actually the default value we have given the
|
|
294
|
+
`useState` hook when we declare it.
|
|
295
|
+
|
|
296
|
+
Go ahead and fill the inputs with your first and last name. Then click the
|
|
297
|
+
button or press enter and see what happens.
|
|
298
|
+
|
|
299
|
+
```jsx live
|
|
300
|
+
import React, { useState } from 'react';
|
|
301
|
+
import Form, { Field } from '@digigov/form';
|
|
302
|
+
import Button from '@digigov/ui/core/Button';
|
|
303
|
+
import Paragraph from '@digigov/ui/typography/Paragraph';
|
|
304
|
+
|
|
305
|
+
export default function SimpleForm() {
|
|
306
|
+
const [submittedData, setSubmittedData] = useState({})
|
|
307
|
+
const handleSubmit = (data) => {
|
|
308
|
+
setSubmittedData(data);
|
|
309
|
+
}
|
|
310
|
+
return <>
|
|
311
|
+
<Form onSubmit={handleSubmit}>
|
|
312
|
+
{/* this is where the fields are going to be placed */}
|
|
313
|
+
<Field
|
|
314
|
+
key="firstName"
|
|
315
|
+
name="firstName"
|
|
316
|
+
label={{ primary: "First name" }}
|
|
317
|
+
type="string"
|
|
318
|
+
required
|
|
319
|
+
/>
|
|
320
|
+
<Field
|
|
321
|
+
key="lastName"
|
|
322
|
+
name="lastName"
|
|
323
|
+
label={{ primary: "Last name" }}
|
|
324
|
+
type="string"
|
|
325
|
+
required
|
|
326
|
+
/>
|
|
327
|
+
<Button type="submit">Continue</Button>
|
|
328
|
+
</Form>
|
|
329
|
+
{<Paragraph>
|
|
330
|
+
You have submitted the following values
|
|
331
|
+
<pre><code>
|
|
332
|
+
{JSON.stringify(submittedData)}
|
|
333
|
+
</code></pre>
|
|
334
|
+
</Paragraph>}
|
|
335
|
+
</>
|
|
336
|
+
}
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
That's great, now we have a form that's actually interactive in some way. The
|
|
340
|
+
inputs are validating data entered and it kindly provides us the submitted data.
|
|
341
|
+
|
|
342
|
+
We're so close to achieve our original goal of a simple working form.
|
|
343
|
+
|
|
344
|
+
## Adding miscellaneous fields
|
|
345
|
+
|
|
346
|
+
It is time to expand our little form and make it render a few more advanced
|
|
347
|
+
fields. We want to get the AFM number, which is used by Greek tax authorities
|
|
348
|
+
and a telephone number. Both of these need custom validations that ensure the
|
|
349
|
+
correct format for user input. Also, we want to get the marital status of our
|
|
350
|
+
users.
|
|
351
|
+
|
|
352
|
+
### AFM & Phone number with validation
|
|
353
|
+
|
|
354
|
+
For these two fields, we can follow exactly the same pattern we have used for
|
|
355
|
+
`firstName` and `lastName` before.
|
|
356
|
+
|
|
357
|
+
In the case of the AFM, the `type` prop will have a value of `afm`. This prop
|
|
358
|
+
will apply the appropriate validation in the Field.
|
|
359
|
+
|
|
360
|
+
Also, please note the use of the `secondary` value in the `label` prop. It is
|
|
361
|
+
used to provide explanation for each field. We can use it to inform users about
|
|
362
|
+
the format of this tax number
|
|
363
|
+
|
|
364
|
+
```jsx
|
|
365
|
+
<Field
|
|
366
|
+
key="taxNumber"
|
|
367
|
+
name="taxNumber"
|
|
368
|
+
type="afm"
|
|
369
|
+
label={{
|
|
370
|
+
primary: "Tax number",
|
|
371
|
+
secondary: "Tax number is your AFM number, given to you by AADE"
|
|
372
|
+
}}
|
|
373
|
+
required
|
|
374
|
+
/>
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
A similar field can be used for the phone number. You can use the
|
|
378
|
+
`type="phone_number"` to validate this field.
|
|
379
|
+
|
|
380
|
+
```jsx
|
|
381
|
+
<Field
|
|
382
|
+
key="phoneNumber"
|
|
383
|
+
name="phoneNumber"
|
|
384
|
+
type="phone_number"
|
|
385
|
+
label={{
|
|
386
|
+
primary: "Phone number",
|
|
387
|
+
secondary: "You can enter any landline phone number."
|
|
388
|
+
}}
|
|
389
|
+
required
|
|
390
|
+
/>
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
### Marital status as a radio group
|
|
394
|
+
|
|
395
|
+
Last but not least, we should create a single choice field, which will be
|
|
396
|
+
rendered as a radio group of answers.
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
```jsx
|
|
400
|
+
<Field
|
|
401
|
+
key="maritalStatus"
|
|
402
|
+
name="maritalStatus"
|
|
403
|
+
type="choice:single"
|
|
404
|
+
label={{primary: "Marital status"}}
|
|
405
|
+
required
|
|
406
|
+
extra={{
|
|
407
|
+
options: [
|
|
408
|
+
{
|
|
409
|
+
label: {primary: "Married"},
|
|
410
|
+
value: 'married',
|
|
411
|
+
},
|
|
412
|
+
{
|
|
413
|
+
label: {primary: "Cohabitation agreement"},
|
|
414
|
+
value: 'cohabitation',
|
|
415
|
+
},
|
|
416
|
+
{
|
|
417
|
+
label: {primary: "Prefer not to answer"},
|
|
418
|
+
value: 'wontanswer',
|
|
419
|
+
}
|
|
420
|
+
]
|
|
421
|
+
}}
|
|
422
|
+
/>
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
## Final form
|
|
426
|
+
|
|
427
|
+
Finally, we have the code almost ready. Let's put it all together by adding the
|
|
428
|
+
few last fields right above the submit button.
|
|
429
|
+
|
|
430
|
+
Feel free to fill the form in the example and submit it.
|
|
431
|
+
|
|
432
|
+
```jsx live
|
|
433
|
+
import React, { useState } from 'react';
|
|
434
|
+
import Form, { Field } from '@digigov/form';
|
|
435
|
+
import Button from '@digigov/ui/core/Button';
|
|
436
|
+
import Paragraph from '@digigov/ui/typography/Paragraph';
|
|
437
|
+
|
|
438
|
+
export default function SimpleForm() {
|
|
439
|
+
const [submittedData, setSubmittedData] = useState({})
|
|
440
|
+
const handleSubmit = (data) => {
|
|
441
|
+
setSubmittedData(data);
|
|
442
|
+
}
|
|
443
|
+
return <>
|
|
444
|
+
<Form onSubmit={handleSubmit}>
|
|
445
|
+
{/* this is where the fields are going to be placed */}
|
|
446
|
+
<Field
|
|
447
|
+
key="firstName"
|
|
448
|
+
name="firstName"
|
|
449
|
+
label={{ primary: "First name" }}
|
|
450
|
+
type="string"
|
|
451
|
+
required
|
|
452
|
+
/>
|
|
453
|
+
<Field
|
|
454
|
+
key="lastName"
|
|
455
|
+
name="lastName"
|
|
456
|
+
label={{ primary: "Last name" }}
|
|
457
|
+
type="string"
|
|
458
|
+
required
|
|
459
|
+
/>
|
|
460
|
+
<Field
|
|
461
|
+
key="taxNumber"
|
|
462
|
+
name="taxNumber"
|
|
463
|
+
type="afm"
|
|
464
|
+
label={{
|
|
465
|
+
primary: "Tax number",
|
|
466
|
+
secondary: "Tax number is your AFM number, given to you by AADE"
|
|
467
|
+
}}
|
|
468
|
+
required
|
|
469
|
+
/>
|
|
470
|
+
<Field
|
|
471
|
+
key="phoneNumber"
|
|
472
|
+
name="phoneNumber"
|
|
473
|
+
type="phone_number"
|
|
474
|
+
label={{
|
|
475
|
+
primary: "Phone number",
|
|
476
|
+
secondary: "You can enter any landline phone number."
|
|
477
|
+
}}
|
|
478
|
+
required
|
|
479
|
+
/>
|
|
480
|
+
<Field
|
|
481
|
+
key="maritalStatus"
|
|
482
|
+
name="maritalStatus"
|
|
483
|
+
type="choice:single"
|
|
484
|
+
label={{primary: "Marital status"}}
|
|
485
|
+
required
|
|
486
|
+
extra={{
|
|
487
|
+
options: [
|
|
488
|
+
{
|
|
489
|
+
label: {primary: "Married"},
|
|
490
|
+
value: 'married',
|
|
491
|
+
},
|
|
492
|
+
{
|
|
493
|
+
label: {primary: "Cohabitation agreement"},
|
|
494
|
+
value: 'cohabitation',
|
|
495
|
+
},
|
|
496
|
+
{
|
|
497
|
+
label: {primary: "Prefer not to answer"},
|
|
498
|
+
value: 'wontanswer',
|
|
499
|
+
}
|
|
500
|
+
]
|
|
501
|
+
}}
|
|
502
|
+
/>
|
|
503
|
+
<Button type="submit">Continue</Button>
|
|
504
|
+
</Form>
|
|
505
|
+
{<Paragraph>
|
|
506
|
+
You have submitted the following values
|
|
507
|
+
<pre><code>
|
|
508
|
+
{JSON.stringify(submittedData)}
|
|
509
|
+
</code></pre>
|
|
510
|
+
</Paragraph>}
|
|
511
|
+
</>
|
|
512
|
+
}
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
Perfect! We now have a finished form, complete with field validation.
|
package/es/Field/utils.js
CHANGED
|
@@ -54,6 +54,7 @@ export function calculateField(children, field, componentRegistry) {
|
|
|
54
54
|
|
|
55
55
|
if (children) {
|
|
56
56
|
calculatedField.component = children;
|
|
57
|
+
calculatedField.controlled = true;
|
|
57
58
|
} else if (typeof field.component === 'function') {// leave as is
|
|
58
59
|
} else if (!field.component && !field.type) {
|
|
59
60
|
var _fieldComponentRegist;
|