@bolttech/form-engine 0.14.3 → 3.0.0-beta.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.
Files changed (79) hide show
  1. package/README.md +2 -1628
  2. package/index.esm.d.ts +1 -0
  3. package/index.esm.js +1683 -0
  4. package/package.json +15 -16
  5. package/src/components/AsFormField/AsFormField.d.ts +4 -0
  6. package/src/components/FieldWrapper/FieldWrapper.d.ts +4 -0
  7. package/src/components/Form/Form.d.ts +4 -0
  8. package/src/components/index.d.ts +2 -0
  9. package/src/context/FormGroupContext.d.ts +27 -0
  10. package/src/generators/formBuilder.d.ts +11 -0
  11. package/src/index.d.ts +3 -3
  12. package/src/types/index.d.ts +47 -0
  13. package/CHANGELOG.md +0 -529
  14. package/asFormField-3108e669.js +0 -2
  15. package/asFormField-3108e669.js.map +0 -1
  16. package/index.js +0 -2
  17. package/index.js.map +0 -1
  18. package/react.js +0 -2
  19. package/react.js.map +0 -1
  20. package/src/adapters/react/Field.d.ts +0 -4
  21. package/src/adapters/react/Form.d.ts +0 -5
  22. package/src/adapters/react/Submit.d.ts +0 -3
  23. package/src/adapters/react/asFormField.d.ts +0 -4
  24. package/src/adapters/react/context.d.ts +0 -5
  25. package/src/adapters/react/index.d.ts +0 -7
  26. package/src/adapters/react/types.d.ts +0 -326
  27. package/src/adapters/react/useForceUpdate.d.ts +0 -3
  28. package/src/adapters/react/useForm.d.ts +0 -12
  29. package/src/adapters/react/useFormGroup.d.ts +0 -3
  30. package/src/core/apis/formatters.d.ts +0 -16
  31. package/src/core/apis/index.d.ts +0 -4
  32. package/src/core/apis/masks.d.ts +0 -3
  33. package/src/core/apis/validations.d.ts +0 -11
  34. package/src/core/apis/varOps.d.ts +0 -4
  35. package/src/core/constants/events.d.ts +0 -32
  36. package/src/core/constants/index.d.ts +0 -5
  37. package/src/core/constants/observer.d.ts +0 -7
  38. package/src/core/events/ObserverError.d.ts +0 -7
  39. package/src/core/events/events.types.d.ts +0 -27
  40. package/src/core/events/index.d.ts +0 -2
  41. package/src/core/handlers/common/templating.d.ts +0 -2
  42. package/src/core/handlers/field/api.d.ts +0 -4
  43. package/src/core/handlers/field/blur.d.ts +0 -2
  44. package/src/core/handlers/field/change.d.ts +0 -2
  45. package/src/core/handlers/field/clearFields.d.ts +0 -4
  46. package/src/core/handlers/field/data.d.ts +0 -3
  47. package/src/core/handlers/field/filter.d.ts +0 -2
  48. package/src/core/handlers/field/focus.d.ts +0 -2
  49. package/src/core/handlers/field/formatters.d.ts +0 -4
  50. package/src/core/handlers/field/htmlEventParser.d.ts +0 -6
  51. package/src/core/handlers/field/keydown.d.ts +0 -2
  52. package/src/core/handlers/field/keyup.d.ts +0 -2
  53. package/src/core/handlers/field/masks.d.ts +0 -4
  54. package/src/core/handlers/field/mount.d.ts +0 -2
  55. package/src/core/handlers/field/validations.d.ts +0 -4
  56. package/src/core/handlers/field/visibilityConditions.d.ts +0 -4
  57. package/src/core/handlers/flows.d.ts +0 -47
  58. package/src/core/handlers/form/bindFields.d.ts +0 -3
  59. package/src/core/handlers/form/hooks.d.ts +0 -3
  60. package/src/core/handlers/form/steps.d.ts +0 -2
  61. package/src/core/handlers/form/templating.d.ts +0 -2
  62. package/src/core/handlers/form/validate.d.ts +0 -2
  63. package/src/core/handlers/form/visibilityConditions.d.ts +0 -4
  64. package/src/core/index.d.ts +0 -3
  65. package/src/core/managers/Base.d.ts +0 -19
  66. package/src/core/managers/Factory.d.ts +0 -52
  67. package/src/core/managers/Field.d.ts +0 -33
  68. package/src/core/managers/Form.d.ts +0 -28
  69. package/src/core/managers/Scope.d.ts +0 -12
  70. package/src/core/managers/index.d.ts +0 -1
  71. package/src/core/types/index.d.ts +0 -937
  72. package/src/core/utils/common.d.ts +0 -9
  73. package/src/core/utils/credit-card.d.ts +0 -16
  74. package/src/core/utils/index.d.ts +0 -6
  75. package/src/core/utils/object.d.ts +0 -27
  76. package/src/core/utils/string.d.ts +0 -3
  77. package/src/core/utils/value.d.ts +0 -2
  78. package/types.js +0 -2
  79. package/types.js.map +0 -1
package/README.md CHANGED
@@ -1,1632 +1,6 @@
1
- # Form Engine - Low code forms
1
+ # Form Engine React Adapter
2
2
 
3
- Achieve form logic re-usage with forms expressed in json format.
4
-
5
- > stable version 0.14.2
6
-
7
- > Note: We do not recommend using versions 0.11.5 and 0.11.6 due to bugs in asFormField that unfortunately appeared with them.
8
- > Note: Unfortunately we don't have compatibility with Next.js 14. This is a work in progress.
9
-
10
- ---
11
-
12
- 1. [Basic setup](#markdown-header-basic-setup)
13
- 2. [Step by step](#markdown-header-step-by-step)
14
- 3. [Form Features](#markdown-header-available-features)
15
- - 3.1. [Validations - Allow form to run validations in the field](#markdown-header-validations)
16
- - 3.1.1. [Named Validations](#markdown-header-validations)
17
- - 3.1.2. [Error Messages](#markdown-header-validations)
18
- - 3.1.3. [Available Validations](#markdown-header-validations)
19
- - 3.2. [Filters - Allow only what you want in the field](#markdown-header-filters)
20
- - 3.2.1. [Available formatters](#markdown-header-formatters)
21
- - 3.3. [Formatters - Style your field value with formatters](#markdown-header-formatters)
22
- - 3.4. [Masks - Modify the field value, while maintaining the original with masks](#markdown-header-masks)
23
- - 3.4.1. [Available Masks](#markdown-header-formatters)
24
- - 3.5. [Visibility conditions - Configure when to show hide/components](#markdown-header-visibility-conditions)
25
- - 3.6. [Clear fields](#markdown-header-clear-fields)
26
- - 3.7. [Api - Make api calls on certain form events](#markdown-header-api)
27
- - 3.8. [Data binding - Allow to have dynamic data in the form, binding and subscribing to form changes](#markdown-header-data-binding)
28
- - 3.8.1. [Scopes](#markdown-header-scope)
29
- - 3.8.2. [Templates](#markdown-header-templates)
30
- - 3.8.3. [varOps](#markdown-header-varops)
31
- - 3.8.4. [Direct Fields Binding](#markdown-header-direct-fields-binding)
32
- - 3.9. [State - Define component state](#markdown-header-state)
33
- - 3.10. [Group](#markdown-header-group)
34
- - 3.11. [Steps](#markdown-header-form-step)
35
- 4. [React](#markdown-header-react-components)
36
- - 4.1. [FormProvider - Provider to configure the form with component mappings](#markdown-header-react-formprovider)
37
- - 4.2. [Form - Component to render a form based on a schema and listen to some events](#markdown-header-react-form)
38
- - 4.3. [useForm hook- Allow to connect to any form in the page](#markdown-header-react-useform)
39
- - 4.4. [useFormGroup hook- Allow to aggregate forms in the page](#markdown-header-react-useformgroup)
40
- - 4.5. [asFormField HOC- Leverage form features but keep the control of your component](#markdown-header-react-asformfield)
41
-
42
- ## **Basic setup**
43
-
44
- Serve your forms in JSON to your frontend, and allow it to be agnostic of your forms logic.
45
-
46
- 3 simple steps
47
-
48
- 1. Map your components to the form (Section - Build your mappers)
49
- 2. Build json schema
50
- 3. Use it
51
-
52
- **1. BUILD MAPPERS**
53
-
54
- ```javascript
55
- import Input from 'Components/Input';
56
- import Other from 'Components/Other';
57
-
58
- const Mappings = {
59
- input: { component: Input },
60
- other: { component: Other },
61
- };
62
-
63
- const formBuilderPropsMapping = {
64
- //default prop names
65
- __default__: {
66
- getValue: 'onChange',
67
- setValue: 'value',
68
- },
69
- //component specific prop names
70
- other: {
71
- getValue: 'onChangeCallback',
72
- setValue: 'data',
73
- setErrorMessage: 'errorMessageArray',
74
- setErrorState: 'isErrored',
75
- onBlur: 'onBlurCallback',
76
- onFocus: 'onFocusCallback',
77
- onKeyUp: 'onKeyUpCallback',
78
- onKeyDown: 'onKeyDownCallback',
79
- },
80
- };
81
-
82
- export { Mappings, formBuilderPropsMapping };
83
- ```
84
-
85
- **2. BUILD SCHEMA**
86
-
87
- ```json
88
- {
89
- "components": [
90
- {
91
- "component": "",
92
- "name": "",
93
- "children": [
94
- {
95
- "component": "${componentName}",
96
- "name": "${componentFormName}",
97
- "props": {
98
- "fullWidth": true
99
- }
100
- }
101
- ]
102
- }
103
- ]
104
- }
105
- ```
106
-
107
- **USE IT (React version)**
108
-
109
- ```javascript
110
- import { Mappings, formBuilderPropsMapping } from './my-component-mappings';
111
- import { getFormSchema } from './my-api-wrapper';
112
- ...
113
- const schema = useMemo(() => getFormSchema('myInstanceContext'), []);
114
-
115
- ...
116
- <Form mappings={Mappings} propsMappings={formBuilderPropsMapping} schema={schema}>
117
- ```
118
-
119
- Nexts steps ? Checkout what you can do in the storybook with `npm run storybook` or see the best effort readme :(
120
-
121
- ## **Step by step**
122
-
123
- ### Build your mappers
124
-
125
- The form uses mappings to connect to UI components so that its easy to connect to any set of components.
126
-
127
- You can build your own mappings file or you can use the `bolttech` and if you want extend it with your set of components.
128
-
129
- In the mappings file you need to specify the component definition and a name to refer in the JSON's latter, and how the form will connect to component props.
130
-
131
- See this example
132
-
133
- ```javascript
134
- import Input from '@bit/bolttech.components.ui.input';
135
- import Checkbox from '@bit/bolttech.components.ui.checkbox';
136
- import FormGroup from '@bit/bolttech.components.common.form-group';
137
-
138
- const Mappings = {
139
- input: { component: Input },
140
- checkbox: { component: Checkbox },
141
- formGroup: { component: FormGroup },
142
- };
143
-
144
- const formBuilderPropsMapping = {
145
- input: {
146
- getValue: 'onChange',
147
- setValue: 'value',
148
- setErrorMessage: 'errorMessage',
149
- setErrorState: 'isErrored',
150
- onBlur: 'onBlur',
151
- onFocus: 'onFocus',
152
- onKeyUp: 'onKeyUp',
153
- onKeyDown: 'onKeyDown',
154
- },
155
- checkbox: {
156
- getValue: 'onChange',
157
- setValue: 'checked',
158
- },
159
- };
160
-
161
- export { Mappings, formBuilderPropsMapping };
162
- ```
163
-
164
- Here you say to the form that you can use in your JSON the names `input`, `checkbox` and `formGroup` and you tell the form how to get the props it needs from them.
165
-
166
- If you have lots of components with the same prop names, you can, and should use `__default__` key. This key allows to reuse prop names.
167
-
168
- Lets say 10 components use to `value` prop name to set the component value, and `onChange` prop name to expose value. You van set your mapper the following way
169
-
170
- ```javascript
171
- import Input from '@bit/bolttech.components.ui.input';
172
- import Checkbox from '@bit/bolttech.components.ui.checkbox';
173
-
174
- const Mappings = {
175
- input: { component: Input },
176
- checkbox: { component: Checkbox },
177
- };
178
-
179
- const formBuilderPropsMapping = {
180
- __default____: {
181
- getValue: 'onChange',
182
- setValue: 'value',
183
- },
184
- checkbox: {
185
- getValue: 'onChange',
186
- setValue: 'checked',
187
- },
188
- };
189
-
190
- export { Mappings, formBuilderPropsMapping };
191
- ```
192
-
193
- ### Setup Form provider
194
-
195
- After setting your own mappings you encapsulate your app of your form with the provider
196
-
197
- ```javascript
198
- <FormProvider mapper={Mappings} propsMapping={formBuilderPropsMapping}>
199
- {children}
200
- </FormProvider>
201
- ```
202
-
203
- **DONE. NOW build your forms**
204
-
205
- ## **Form Features**
206
-
207
- Inside the schema you can specify several actions for a field alone or that correlate and have side-effects between them.
208
-
209
- Those actions support multiple lifecycle and this must be on an action item basis:
210
-
211
- - ON_FIELD_MOUNT
212
- - ON_FIELD_CHANGE
213
- - ON_FIELD_BLUR
214
- - ON_FIELD_FOCUS
215
- - ON_FIELD_KEYUP
216
- - ON_FIELD_KEYDOWN
217
- - ON_FIELD_CLICK
218
- - ON_FIELD_CLEARED
219
- - ON_FIELD_BINDED
220
- - AFTER_FIELD_API_CALL
221
-
222
- All the actions are typed, so you will have help here seeing which lifecycles you have available
223
-
224
- Per action, you will be able to combine multiple lifecycle methods
225
-
226
- All the following features can be inserted in the same location on the schema
227
-
228
- ```json
229
- {
230
- "component": "input",
231
- "name": "fieldName",
232
- "props": {
233
- "label": "My field"
234
- }
235
- //...your feature goes here
236
- }
237
- ```
238
-
239
- ## **Validations**
240
-
241
- Like the name say, this feature lets you validate the form in the several lifecycle events of the form.
242
-
243
- ```json
244
- {
245
- "validations": {
246
- "ON_FIELD_BLUR": {
247
- "email": true
248
- },
249
- "ON_FIELD_CHANGE": {
250
- "required": true
251
- }
252
- }
253
- }
254
- ```
255
-
256
- The above example will let form know that in each change the field must have something in it, and that on blur, the value must be a email.
257
-
258
- ### Named validations
259
-
260
- There are cases where you want to build your own validation, agregating several of giving it a specific name that you can refer later
261
-
262
- ```json
263
- {
264
- "validations": {
265
- "ON_FIELD_BLUR": {
266
- "blurRequire": {
267
- "require": true
268
- }
269
- },
270
- "ON_FIELD_CHANGE": {
271
- "email": true,
272
- "changeRequire": {
273
- "require": true
274
- },
275
- "changeRestOfValidations": {
276
- "length": 50
277
- //...
278
- }
279
- }
280
- }
281
- }
282
- ```
283
-
284
- ### Error Messages
285
-
286
- You can also specify the error messages you want.
287
-
288
- ```json
289
- {
290
- "validations": {
291
- "ON_FIELD_BLUR": {
292
- "require": true
293
- },
294
- "ON_FIELD_CHANGE": {
295
- "email": true
296
- }
297
- },
298
- "errorMessages": {
299
- "default": "Default error message",
300
- "email": "Invalid e-mail"
301
- }
302
- }
303
- ```
304
-
305
- This schema part, will add messages to validations error.
306
-
307
- - Each time the field has an e-mail error it will send the "Invalid e-mail" message to the component
308
- - If there is and field error, but no message is specified, it will send what you have in `default` key. In this example, `required` error does not have message and will send "Default error message"
309
-
310
- **With named validations**
311
-
312
- If you have a named validation, you can use its name in the error messages, having better granularity on it.
313
-
314
- ```json
315
- {
316
- "validations": {
317
- "ON_FIELD_BLUR": {
318
- "blurRequire": {
319
- "require": true
320
- }
321
- },
322
- "ON_FIELD_CHANGE": {
323
- "email": true,
324
- "changeRequire": {
325
- "require": true
326
- },
327
- "changeRestOfValidations": {
328
- "length": 50
329
- //...
330
- }
331
- }
332
- },
333
- "errorMessages": {
334
- "default": "Default error message",
335
- "email": "Invalid e-mail",
336
- "blurRequire": "When you blur, this component is required",
337
- "changeRequire": "You should not leave the field blank",
338
- "changeRestOfValidations": "You are changing into an incorrect state"
339
- }
340
- }
341
- ```
342
-
343
- ### Available validations (TBD)
344
-
345
- Refer to the `TAvailableValidations` types here:
346
-
347
- ````typescript
348
- {
349
- /**
350
- * The bool function is a validation function that checks if a given value indicating whether the validation has failed or not.
351
- *
352
- * @example - in a test environment
353
- * ```
354
- * const result = bool({
355
- * validationValue: false,
356
- * });
357
- * console.log(result); // { fail: false }
358
- * ```
359
- *
360
- * @example - real json usage with field value
361
- * ```
362
- * {
363
- * validations: {
364
- * bool: '${fields.input.value}'
365
- * },
366
- * },
367
- * ```
368
- *
369
- * @example - real json usage with iVar value
370
- * ```
371
- * {
372
- * validations: {
373
- * bool: '${global.validation}'
374
- * },
375
- * },
376
- * ```
377
- */
378
- bool?: string | boolean;
379
- /**
380
- * Validation based on conditions
381
- *
382
- * @example - Compare own field to two. Origin and target default to field value
383
- * ```
384
- * conditions: {
385
- * rule: 'and',
386
- * set: [
387
- * {
388
- * condition: '===',
389
- * target: '2',
390
- * },
391
- * {
392
- * origin: '2',
393
- * condition: '===',
394
- * },
395
- * ],
396
- * },
397
- * ```
398
- * @example - Binded to Postcode field value. Must be greater than or equal two
399
- * ```
400
- * conditions: {
401
- * rule: 'or',
402
- * set: [
403
- * {
404
- * origin: '${fields.postcode.value}',
405
- * condition: '>',
406
- * target: '2',
407
- * },
408
- * {
409
- * origin: '${fields.postcode.value}',
410
- * condition: '===',
411
- * target: '2',
412
- * },
413
- * ],
414
- * },
415
- * ```
416
- * @example - Binded to Postcode field value. Must be equal to two
417
- * ```
418
- * conditions: {
419
- * rule: 'or',
420
- * set: [
421
- * {
422
- * origin: '${fields.postcode.value}',
423
- * condition: '===',
424
- * target: '2',
425
- * },
426
- * ],
427
- * },
428
- * ```
429
- */
430
- conditions?: TVAvailableValidationConditions;
431
- /**
432
- * Applies multiple validations on the given value based on the specified truth table rule.
433
- *
434
- * @param {Object} TVAvailableValidationMultipleValidations - The multiple validations object param.
435
- * @param {'AND' | 'OR' | 'NOT'} TVAvailableValidationMultipleValidations.rule - The rule to be applied based of truth table ('AND', 'OR', or 'NOT').
436
- * @param {Object} TVAvailableValidationMultipleValidations.validations - Object containing validation rules.
437
- *
438
- * @example - Validating with the expression AND where current field must have a value of 'yes' and input 2 must have a value of 'no'
439
- * ```
440
- * multipleValidations: {
441
- * rule: 'AND',
442
- * validations: {
443
- * value: 'yes',
444
- * conditions: {
445
- * rule: 'and',
446
- * set: [
447
- * {
448
- * origin: '${fields.input2.value}',
449
- * condition: '===',
450
- * target: 'no'
451
- * },
452
- * ],
453
- * },
454
- * },
455
- * },
456
- * ```
457
- * @example - Validating with the expression OR where current field must have a value of '1995-12-12' or be a valid date with regex
458
- * ```
459
- * multipleValidations: {
460
- * rule: 'OR',
461
- * validations: {
462
- * value: '1995-12-12',
463
- * regex: '^\d{4}-\d{2}-\d{2}$',
464
- * },
465
- * },
466
- * ```
467
- * @example - Validating with the expression NOT where current field doesn't have a value of '1995-12-12' and not be a valid date with regex
468
- * ```
469
- * multipleValidations: {
470
- * rule: 'NOT',
471
- * validations: {
472
- * value: '1995-12-12',
473
- * regex: '^\d{4}-\d{2}-\d{2}$',
474
- * },
475
- * },
476
- * ```
477
- */
478
- multipleValidations?: TVAvailableValidationMultipleValidations;
479
- /**
480
- * Between validations
481
- *
482
- * @example - Between ages
483
- * ``` type teste = Pick<TVAvailableValidations, 'date'>
484
- * between: {
485
- * dates: [
486
- * {
487
- * operator: '>=',
488
- * origin: {
489
- * format: 'YYYYMMDD',
490
- * intervals: {
491
- * years: 18,
492
- * },
493
- * },
494
- * },
495
- * {
496
- * operator: '<=',
497
- * origin: {
498
- * format: 'YYYYMMDD',
499
- * intervals: {
500
- * years: 75,
501
- * },
502
- * },
503
- * }
504
- * ]
505
- * }
506
- * ```
507
- *
508
- * @example - Between numbers
509
- * ```
510
- * between: {
511
- * start: '3',
512
- * end: '4',
513
- * isIncludedBoundaries: true
514
- * },
515
- * ```
516
- *
517
- */
518
- between?: {
519
- /**
520
- * Array of date validations. To make it possible, ensure that the conditions is > and < in both date validations.
521
- */
522
- dates?: TVAvailableValidations['date'][];
523
- /**
524
- * The first number of the validation. If the current value is grater than this number, the validation will pass.
525
- */
526
- start?: number;
527
- /**
528
- * The second number of the validation. If the current value is lower than this number, the validation will pass.
529
- */
530
- end?: number;
531
- /**
532
- * If it's true, the comparision is transformed to >= and <=. So, the numbers that were passed are included in the validation.
533
- */
534
- isIncludedBoundaries?: boolean;
535
- };
536
- /**
537
- * Dates validations
538
- *
539
- * @example - Dates should be different
540
- * ```
541
- * date: {
542
- * operator: '!==',
543
- * origin: {
544
- * format: 'DDMMYYYY',
545
- * },
546
- * target: {
547
- * format: 'DDMMYYYY',
548
- * value: '10/10/2001',
549
- * },
550
- * },*
551
- * ```
552
- *
553
- * @example - Compare only valid dates using intervals
554
- * ```
555
- * date: {
556
- * onlyValidDate: true,
557
- * operator: '<',
558
- * origin: {
559
- * format: 'DD/MM/YYYY',
560
- * intervals: {
561
- * years: 1,
562
- * },
563
- * },
564
- * },
565
- * ```
566
- *
567
- * @example - Should have at max 85 years
568
- * ```
569
- * {
570
- * operator: '>',
571
- * origin: {
572
- * format: 'DDMMYYYY',
573
- * value: eightyFiveYearsDate,
574
- * intervals: {
575
- * years: 85,
576
- * },
577
- * },
578
- * }
579
- * }
580
- *
581
- * ```
582
- */
583
- date?: {
584
- /**
585
- * Flag to force only valid dates. Valid dates must be of min length of 8
586
- */
587
- onlyValidDate?: boolean;
588
- /**
589
- * List of operations you can do
590
- * - between origin and target dates
591
- * - between origin and intervals
592
- */
593
- operator: TValidationDateOperators;
594
- /**
595
- * The origin configurations
596
- */
597
- origin: {
598
- /**
599
- * Origin date value
600
- */
601
- value?: string | number;
602
- /**
603
- * The available date formats
604
- */
605
- format: TValidationDateFormats;
606
- /**
607
- * Intervals to compare with the original date.
608
- *
609
- * It will use todays date for comparison.
610
- *
611
- * @example
612
- *
613
- * origin date = 10/10/2022
614
- * interval.year = 1
615
- * operator = '==='
616
- *
617
- * It will compare (10/10/2022 + 1) with the current date and check if they are the same
618
- */
619
- intervals?: {
620
- years?: number;
621
- months?: number;
622
- days?: number;
623
- };
624
- };
625
- target?: {
626
- value: string | number;
627
- format: TValidationDateFormats;
628
- };
629
- };
630
- /**
631
- * Allow to validate if the input string is a valid date format
632
- */
633
- validDate?: TValidationDateFormats;
634
- /**
635
- * Allow to define a maximum length for the input to have no error
636
- */
637
- length?: number;
638
- /**
639
- * Will look into the input length and send an error if if not greater than this value
640
- */
641
- greaterThan?: number | string;
642
-
643
- /**
644
- * Specifies a regular expression pattern that the value should match.
645
- */
646
- regex?: string;
647
-
648
- /**
649
- * Specifies the maximum length of the value (if it's a string).
650
- */
651
- maxLength?: number;
652
-
653
- /**
654
- * Specifies the minimum length of the value (if it's a string).
655
- */
656
- minLength?: number;
657
-
658
- /**
659
- * Specifies whether the field is required.
660
- */
661
- required?: boolean;
662
-
663
- /**
664
- * Specifies that the value should contain only letters.
665
- */
666
- onlyLetters?: boolean;
667
-
668
- /**
669
- * Specifies a value that the field should match.
670
- */
671
- value?: string | number | boolean;
672
-
673
- /**
674
- * Specifies that the field should not be empty.
675
- */
676
- notEmpty?: boolean;
677
-
678
- /**
679
- * A callback function that performs custom validation on the value.
680
- * @param value - The value to be validated.
681
- * @returns An object with validation results.
682
- */
683
- callback?(value: string | number): { fail: boolean; errorMessage?: string };
684
-
685
- /**
686
- * Specifies a numeric range for the value.
687
- */
688
- numericRange?: { start: number | string; end: number | string };
689
-
690
- /**
691
- * Specifies whether the value should be a number.
692
- */
693
- isNumber?: boolean;
694
-
695
- /**
696
- * Specifies that the field should not have extra spaces.
697
- */
698
- hasNoExtraSpaces?: boolean;
699
-
700
- /**
701
- * Specifies that the value should be an email address.
702
- */
703
- email?: boolean;
704
-
705
- /**
706
- * Specifies that the value should be less than a given number or string.
707
- */
708
- lessThan?: number | string;
709
-
710
- /**
711
- * Specifies that the value should be a sequential number.
712
- */
713
- sequentialNumber?: boolean;
714
-
715
- /**
716
- * Specifies that the value should not contain repeated numbers.
717
- */
718
- repeatedNumbers?: boolean;
719
-
720
- /**
721
- * Specifies that the value should be a URL.
722
- */
723
- url?: boolean;
724
-
725
- /**
726
- * Specifies a path error type.
727
- */
728
- path?: TPathError;
729
-
730
- /**
731
- * Specifies that the value should be a valid credit card number.
732
- */
733
- isCreditCard?: string[];
734
-
735
- /**
736
- * Specifies that the value should be a valid credit card number with a specific length.
737
- */
738
- isCreditCardAndLength?: string[];
739
-
740
- /**
741
- * Specifies that the value should match a credit card code with available options.
742
- */
743
- isCreditCodeMatch?: { numberCard: string; availableOptions: string[] };
744
-
745
- /**
746
- * Specifies custom validation options for the field.
747
- */
748
- customValidation?: ICustomValidationValue[];
749
-
750
- /**
751
- * Specifies that spaces are not allowed in the field.
752
- */
753
- notAllowSpaces?: true;
754
-
755
- /**
756
- * Specifies that the value should be in a predefined list of values.
757
- */
758
- isInTheList?: string[] | number[] | string;
759
-
760
- /**
761
- * Specifies field validation rules for nested fields.
762
- */
763
- fields?: {
764
- /**
765
- * The rule for validating nested fields (e.g., 'every').
766
- */
767
- rule: 'every';
768
-
769
- /**
770
- * An array of nested field validation configurations.
771
- */
772
- set: {
773
- /**
774
- * The binding for the nested field.
775
- */
776
- bind: string;
777
-
778
- /**
779
- * The field name for the nested field.
780
- */
781
- fieldName: string;
782
-
783
- /**
784
- * Validation options for the nested field, excluding the 'fields' property.
785
- */
786
- validations: Omit<TVAvailableValidations, 'fields'>;
787
- }[];
788
- };
789
-
790
- /**
791
- * Specifies that the value should be existed.
792
- */
793
- exists?: string | number ;
794
- }
795
- ````
796
-
797
- ## **Formatters**
798
-
799
- Formatting a field means mutating the field value to a given... format.
800
-
801
- This options will allow you to force a give field to have the format you whant while the user is performing some action on the form.
802
-
803
- **NOTE** - When receiving the values of the form, you will have the value with the specified format, not the raw value the user entered
804
-
805
- You have several formatters. THe following example shows splitter that is a more generic one, allowing you to split the input text
806
-
807
- **BIG NOTE** - Formatters won't execute when a value is deleting (eg. user pressed backspace to delete a character), to execute on every
808
- value change, use masks instead
809
-
810
- ```json
811
- {
812
- "formatters": {
813
- "ON_FIELD_MOUNT": {
814
- "splitter": [
815
- {
816
- "position": 2,
817
- "value": "/"
818
- },
819
- {
820
- "position": 5,
821
- "value": "/"
822
- }
823
- ]
824
- }
825
- }
826
- }
827
- ```
828
-
829
- The above example will split your word in position 2 and 5, adding there the `/`. This will give you a date format like `10/10/1987` (you would have to limit the input length. More on that on FILTERS)
830
-
831
- ### Available Formatters (TBD)
832
-
833
- Refer to the types on `TSchema`
834
-
835
- #### Regex
836
-
837
- Specifies a regular expression pattern that the value should match to be replaced.
838
-
839
- ```json
840
- {
841
- "formatters": {
842
- "ON_FIELD_MOUNT": {
843
- "regex": "[0-9]"
844
- }
845
- }
846
- }
847
- ```
848
-
849
- #### Callback
850
-
851
- Specifies a function that will format the field
852
-
853
- ```typescript
854
- const removeDots = (value: string | number): string | number => {
855
- return value.split('.').join('');
856
- };
857
-
858
- const formatterInstance = {
859
- formatters: {
860
- ON_FIELD_CHANGE: {
861
- callback: removeDots,
862
- },
863
- },
864
- };
865
- ```
866
-
867
- ## Masks
868
-
869
- Mask has the same functionality of formatter, but keed the original value for your program. Think of it like the password mask. You input something into your text input, mask that something with `*` but you need to read the original value. FOr Eg.
870
-
871
- ```json
872
- {
873
- "masks": {
874
- "ON_FIELD_BLUR": {
875
- "replaceAll": "*"
876
- },
877
- "ON_FIELD_FOCUS": {
878
- "cleanMask": true
879
- }
880
- }
881
- }
882
- ```
883
-
884
- In this example, you will
885
-
886
- - Mask a given text input from for example `123345` to `******`
887
- - On Focus , you tell form to clean the mask with `cleanMask` directive.
888
-
889
- ### Available Masks (TBD)
890
-
891
- Refer to the types on `TSchema`
892
-
893
- #### Callback
894
-
895
- Specifies a function that will format the field
896
-
897
- ```typescript
898
- const removeDots = (value: string | number): string | number => {
899
- return value.split('.').join('');
900
- };
901
-
902
- const formatterInstance = {
903
- formatters: {
904
- ON_FIELD_CHANGE: {
905
- callback: removeDots,
906
- },
907
- },
908
- };
909
- ```
910
-
911
- ## **Filters**
912
-
913
- Filters very predictable and work like the word says, they filter a given word to a given patter/directive.
914
-
915
- Lets say you want a field to accept only numbers and with a max length o X.
916
-
917
- ```json
918
- {
919
- "filter": {
920
- "ON_FIELD_CHANGE": {
921
- "length": 4,
922
- "isNumber": true
923
- }
924
- }
925
- }
926
- ```
927
-
928
- This example will let you do just that. Only numbers and max length of 4
929
-
930
- ### Available filters (TBS)
931
-
932
- Refer to the types on `TSchema`
933
-
934
- ## Visibility conditions
935
-
936
- ### Field level
937
-
938
- Sometimes you want to hide other fields based on certain conditions.
939
-
940
- That is what this feature does.
941
-
942
- Eg: You want to hide another field, when a given field `originalField` has a given value on it.
943
-
944
- ```json
945
- [
946
- {
947
- "name": "originalField",
948
- "component": "checkbox",
949
- "visibilityConditions": {
950
- "ON_FIELD_MOUNT": [
951
- {
952
- "validations": {
953
- "value": "Yes"
954
- },
955
- "fieldName": "targetField"
956
- }
957
- ],
958
- "ON_FIELD_CHANGE": [
959
- {
960
- "validations": {
961
- "value": "Yes"
962
- },
963
- "fieldName": "targetField"
964
- }
965
- ]
966
- },
967
- "props": {
968
- //...
969
- }
970
- },
971
- {
972
- "name": "targetField",
973
- "component": "input",
974
- "props": {
975
- //...
976
- }
977
- }
978
- ]
979
- ```
980
-
981
- This example tells form to
982
-
983
- - On mount check if `originalField` has the value `Yes`
984
- - If it put the `targetField` visible
985
- - Otherwise, make it invisible
986
-
987
- You can also for each visibility condition, apply it to multiple field names with `fieldNames` key that will accept an array.
988
-
989
- ```json
990
- {
991
- "visibilityConditions": {
992
- "ON_FIELD_MOUNT": [
993
- {
994
- "validations": {
995
- "value": "Yes"
996
- },
997
- "fieldNames": ["targetFieldOne", "targetFieldTwo"]
998
- }
999
- ]
1000
- }
1001
- }
1002
- ```
1003
-
1004
- **NOTE** - When the field is hidden using this feature, the form will not try to validate it and will not be accounted to the general form state
1005
-
1006
- ### Form Level
1007
-
1008
- You can also use those in form level.
1009
-
1010
- ```javascript
1011
- <Form
1012
- iVars={{ roofUpdated: state }}
1013
- initialValues={{ roofUpdatedYear: 'diogos' }}
1014
- schema={{
1015
- visibilityConditions: {
1016
- ON_FORM_MOUNT: [
1017
- {
1018
- validations: {
1019
- value: '${global.roofUpdated}',
1020
- },
1021
- fieldName: 'roofUpdatedYear',
1022
- },
1023
- ],
1024
- ON_FIELD_CHANGE: [
1025
- {
1026
- validations: {
1027
- value: 'abc',
1028
- },
1029
- fieldName: 'roofUpdatedYear',
1030
- },
1031
- ],
1032
- },
1033
- components: [{...}],
1034
- }}
1035
- />
1036
- ```
1037
-
1038
- in the above example we are applying the rule:
1039
-
1040
- - in form mount we will hide the value when the `roofUpdatedYear` equals to the iVar `roofUpdated`
1041
- - in each field change we will hide the value when the `roofUpdatedYear` equals to `abc`
1042
- - also you can use the prop `rule` to decide what type of validations rules to execute (and == every | or == some)
1043
- - if you want to show an field only if all or at least one validation is true, use `showOnlyIfTrue` property.
1044
-
1045
- ## Clear Fields
1046
-
1047
- Guess what... THis will clear one or more form fields :)
1048
-
1049
- Uses the same mechanism of VISIBILITY CONDITIONS.
1050
-
1051
- Let's say you want to clear a given field when `originalField` has a given value.
1052
-
1053
- ```json
1054
- {
1055
- "clearFields": {
1056
- "ON_FIELD_CHANGE": [
1057
- {
1058
- "validations": {
1059
- "value": "Yes"
1060
- },
1061
- "field": "targetValue",
1062
- "clearedValue": false
1063
- }
1064
- ]
1065
- }
1066
- }
1067
- ```
1068
-
1069
- When form fires ON_CHANGE this will have the effect of having the field `targetValue` with the value `false` if `originalField` has value `Yes`.
1070
-
1071
- Just like before, you can specify multiple fields with `fields` key for the same rule.
1072
-
1073
- ```json
1074
- {
1075
- "clearFields": {
1076
- "ON_FIELD_CHANGE": [
1077
- {
1078
- "validations": {
1079
- "value": "Yes"
1080
- },
1081
- "fields": ["targetValue"],
1082
- "clearedValue": false
1083
- }
1084
- ]
1085
- }
1086
- }
1087
- ```
1088
-
1089
- Additionally, you can specify multiple props to be changed or cleared from the fields that you specified before using `clearedProps`.
1090
- Each prop will be changed using the respective field. For example, if I have `fields['input', 'checkbox']` then I need to change the input label
1091
- I can send it as `clearedProps: [{ label: 'value' }]` or `clearedProps: { label: 'value' }`. And only input props will be changed.
1092
- It's useful when we have some API calls whose response will be used as a prop value in the component.
1093
-
1094
- ```json
1095
- {
1096
- "clearFields": {
1097
- "ON_FIELD_CHANGE": [
1098
- {
1099
- "validations": {
1100
- "value": "Yes"
1101
- },
1102
- "field": "targetValue",
1103
- "clearedValue": false,
1104
- "defaultClearedValue": true,
1105
- "defaultClearedProps": {
1106
- "disabled": false
1107
- }
1108
- }
1109
- ]
1110
- }
1111
- }
1112
- ```
1113
-
1114
- If you want to set a value when the validation passes you can set `defaultClearedValue` prop on the event to set a value on the cleared field.
1115
- Useful after an API call to set a default response value or a value stored earlier.
1116
- You can also set a `defaultClearedProps` attribute to change the props of the component if the validation passes.
1117
-
1118
- For definition clearValues runs validations on the target field and not on the field it is declaring.
1119
- Therefore, you can set `useCurrentFieldValidation` prop with true if you want validations to be performed on the current field.
1120
-
1121
- > Remember, clearValues only performs `rehydration` on the target field, that is, if your target field has an api call, for example,
1122
- > you must listen to the `ON_FIELD_CLEARED` event to execute such a call on the target field.
1123
-
1124
- ## Api
1125
-
1126
- This one will let you instruct form to call a give API at a given lifecycle method
1127
-
1128
- ```json
1129
- {
1130
- "api": {
1131
- "ON_FIELD_CHANGE": [
1132
- {
1133
- "blockRequestWhenInvalid": true,
1134
- "method": "GET",
1135
- "url": "https://api.chucknorris.io/jokes/random",
1136
- "scope": "chuck"
1137
- }
1138
- ]
1139
- }
1140
- }
1141
- ```
1142
-
1143
- The above example will make form to call the API specified when the field where we gave the directory changes.
1144
-
1145
- ### Keys
1146
-
1147
- | key | type | Description |
1148
- | ----------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1149
- | blockRequestWhenInvalid | boolean | Specify if this call should be blocked when the field is invalid (due to validations) |
1150
- | method | string | HTTP verb. Get, Post, Put or delete |
1151
- | url | string | The api url |
1152
- | scope | string | This lets you put the api result inside the form scope in the given key. THis will allow to use the call result latter on on some field |
1153
- | body | object | Body to send to the API |
1154
- | headers | object | Api headers |
1155
- | fieldValueAsParams | object | An object with key (name of the field in the form) and value (name that I want to be in the query, which if nothing is passed, uses the name of the field as the key) and then it transforms it into a query string |
1156
- | fieldValueAsPathParams | array of strings | an array of field names where he uses it as a key to capture the value and transforms it into path param |
1157
- | debounceTime | number | Allow you to debounce the api call by X seconds |
1158
- | preConditions | TValidations | Allow you to specify validations that should not fail in order to call the API |
1159
-
1160
- ### PreConditions
1161
-
1162
- You can specify the pre-conditions that need to be met, in order for the request to start.
1163
-
1164
- ```json
1165
- {
1166
- "api": {
1167
- "ON_FIELD_CHANGE": [
1168
- {
1169
- "method": "GET",
1170
- "url": "https://api.chucknorris.io/jokes/random",
1171
- "scope": "chuck",
1172
- "preConditions": {
1173
- "required": true,
1174
- "value": "run"
1175
- }
1176
- }
1177
- ]
1178
- }
1179
- }
1180
- ```
1181
-
1182
- In the above example, the api specified will only be called
1183
-
1184
- 1. When field has changes
1185
- 2. When field has values (required validation)
1186
- 3. When the field value is "run"
1187
-
1188
- ### FieldValueAsParams
1189
-
1190
- You can add as many query parameters as you want, but remember that it will search for a field that exists, otherwise it will not be included in the call.
1191
-
1192
- ```json
1193
- {
1194
- "api": {
1195
- "ON_FIELD_CHANGE": [
1196
- {
1197
- "method": "GET",
1198
- "url": "https://api.chucknorris.io/jokes",
1199
- "scope": "chuck",
1200
- "fieldValueAsParams": {
1201
- "input": "name",
1202
- "date": ""
1203
- }
1204
- }
1205
- ]
1206
- }
1207
- }
1208
- ```
1209
-
1210
- From the example above, the call will have the following structure:
1211
-
1212
- ```bash
1213
- # GET https://api.chucknorris.io/jokes?name=random&date=2013-20-01
1214
- ```
1215
-
1216
- When one of the parameters has a key but no value, the key will be reused in the query string.
1217
-
1218
- ### FieldValueAsPathParams
1219
-
1220
- With this parameter, it is possible to use the value of any form field as path param for the http call, as follows:
1221
-
1222
- ```json
1223
- {
1224
- "api": {
1225
- "ON_FIELD_CHANGE": [
1226
- {
1227
- "method": "GET",
1228
- "url": "https://api.chucknorris.io/jokes",
1229
- "scope": "chuck",
1230
- "fieldValueAsPathParams": ["input", "date"]
1231
- }
1232
- ]
1233
- }
1234
- }
1235
- ```
1236
-
1237
- From the example above, the call will have the following structure:
1238
-
1239
- ```bash
1240
- # GET https://api.chucknorris.io/jokes/random/2013-20-01
1241
- ```
1242
-
1243
- So far he only puts one after the other, he still doesn't have the intelligence to choose where to put each.
1244
-
1245
- ## Data binding
1246
-
1247
- Form has a functionality to allow you to build your logic inside the schema via templating.
1248
-
1249
- You can emit and register to data between fields. For example, in the following example field `one` will register to changes on field `two` and its label will have the field `two` value. This is accomplished with [scopes](#scope).
1250
-
1251
- ```json
1252
- [
1253
- {
1254
- "name": "one",
1255
- "component": "input",
1256
- "props": {
1257
- "label": "${fields.two.value}"
1258
- }
1259
- },
1260
- {
1261
- "name": "one",
1262
- "component": "input",
1263
- "props": {
1264
- //...
1265
- }
1266
- }
1267
- ]
1268
- ```
1269
-
1270
- The subscription is done using the template first keys. In this case `fields` and `two`. Telling the engine that anytime the namespace `fields` and key `two` changes it should fire a notification to anyone interested. In this case, field `one` is interested
1271
-
1272
- ### Scope
1273
-
1274
- For templating to work, form relies on scope. The definition of scope is just a datastructures that has multiple keys each one with their context. The following table explain the namespaces
1275
-
1276
- | namespace | description |
1277
- | --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1278
- | global | This namespace contains all the data that comes from the client implementing the Form and is injected in iVars |
1279
- | fields | Automatically generated scope. This namespace contains all the fields with everything that is done in them per field. Eg: value, errors, visible, mask etc. Refer to the types for more info |
1280
- | api | This scope is where you can store the api responses with the api scope key. |
1281
- | hooks | This one is retrieved by the hooks configured on the client |
1282
- | configs | All the configs that the client gave to the form, will be stored here |
1283
-
1284
- Templating basically allows a given component to subscribe to any scope change, be notified and changed according to that. In the following example, the component named `make` is subscribed to `api` namespace on `data` key.
1285
-
1286
- ```json
1287
- {
1288
- "name": "make",
1289
- "component": "dropdown",
1290
- "props": {
1291
- "id": "make",
1292
- "name": "make",
1293
- "label": "Make",
1294
- "placeholder": "",
1295
- "options": "${api.makes.data||[]}"
1296
- }
1297
- }
1298
- ```
1299
-
1300
- This means that, anytime that `api.makes.data` changes (done by api action with scope = data), this component will be injected with its value on the `options` key. It also has a default value of empty array `...data||[]}`.
1301
-
1302
- If you want you can even nest templating also. Next example we will access to `global` namespace on `name` key. But we will access the prop dynamically from the field named `myfield` value
1303
-
1304
- ```json
1305
- {
1306
- "component": "input",
1307
- "name": "destination",
1308
- "props": {
1309
- "name": "destination",
1310
- "label": "Dynamic -> ${global.name.${fields.myfield.value||test}}"
1311
- }
1312
- }
1313
- ```
1314
-
1315
- This will result in the following. Assume we have scope like
1316
-
1317
- ```json
1318
- {
1319
- "global": {
1320
- "name": {
1321
- "test": "test",
1322
- "other": "other"
1323
- }
1324
- }
1325
- }
1326
- ```
1327
-
1328
- It will access `global.name.test` since we have the default value as test and there is no data in fields scope. The end result would be _"Dynamic -> test"_
1329
-
1330
- But right after input on the form field named `myfield`, its scope will be populated
1331
-
1332
- ```json
1333
- {
1334
- "global": {
1335
- "name": {
1336
- "test": "test",
1337
- "other": "other"
1338
- }
1339
- },
1340
- "fields": {
1341
- "myfield": {
1342
- "value": "other"
1343
- //...
1344
- }
1345
- }
1346
- }
1347
- ```
1348
-
1349
- In this case would access `global.name.other` and the final result would be _"Dynamic -> other"_
1350
-
1351
- ### Templates
1352
-
1353
- We talked about templates, but let's go a step further. THe definition of template, is a just a string that has a given prefix and suffix like `${...}`.
1354
-
1355
- Whatever comes inside the delimiters will be later extracted by the engine and mapped with the current scope in order to find a replacement value.
1356
-
1357
- The only limitation is that the template must be a string representing an object path. That object path will be looked for in the [scope](#scope) like `#{api.myapicall.response.data.value}`.
1358
-
1359
- **Default values**
1360
-
1361
- You can set template default values with `||` like `${fields.foo.value||default-value}`. This will lead to, if the scope has value in `fields.foo` set the value in template value, otherwise set the string `default-value`.
1362
- You can also use as many values as you want as defaults. Only what is valid and has a value will go into the field, otherwise it will be undefined.
1363
-
1364
- **Template nesting**
1365
-
1366
- You can also nest multiple templates reaching extreme situations. For example
1367
-
1368
- `${fields.${gloval.fieldname||foo}.value||novalue}`
1369
-
1370
- This example will give you the following possible replacements:
1371
-
1372
- - If `global.fieldname` exists and has value `bar` for example, and form `bar` field contains value lets say value 2 - Output will be 2
1373
- - If `global.fieldname` exists and has value `bar` for example, and form `bar` field does not contain value - Output will be non value
1374
- - If `global.fieldname` does not exists , and form `foo` field does not contain value - Output will be non value
1375
- - If `global.fieldname` does not exists , and form `foo` field contains value lets say value 3 - Output will be 3
1376
-
1377
- ### VarOps
1378
-
1379
- Templates are already a great power of form-engine, but we can go further allowing operations to be specified in the schema. Those operations are all under `varOps` (variable operations).
1380
-
1381
- ```json
1382
- {
1383
- "component": "input",
1384
- "name": "password",
1385
- "errorMessages": {
1386
- "required": "Password is required",
1387
- "value": "Error value must be varOps.concatenate(${fields.email.value||0},${fields.email2.value||0})"
1388
- },
1389
- "validations": {
1390
- "ON_FIELD_CHANGE": {
1391
- "required": true,
1392
- "value": "varOps.concatenate(${fields.email.value||0},${fields.email2.value||0})"
1393
- }
1394
- },
1395
- "props": {
1396
- "variants": "default_border",
1397
- "placeholder": "Please enter your password",
1398
- "label": "Password"
1399
- }
1400
- }
1401
- ```
1402
-
1403
- In the example the validation value comes from a `varOps`. This example uses the `concatenate` operations exposed by the engine.
1404
-
1405
- Here this field (`password`) will register with [templating](#templates) to field `email` and `email2`. Meaning, each time they change this field schema will be recomputed with what changed to replace the needed values.
1406
-
1407
- When this happens, lets say `email` has value foo and `email2` value bar. The `varOp` concatenate will be called with the correct field replaced values
1408
-
1409
- ```javascript
1410
- varOps.concatenate('foo', 'bar');
1411
- ```
1412
-
1413
- This will map to an operation function and the function return value will be replaced by the varOps like
1414
-
1415
- ```json
1416
- {
1417
- "validations": {
1418
- "ON_FIELD_CHANGE": {
1419
- "required": true,
1420
- "value": "foo_bar"
1421
- }
1422
- }
1423
- }
1424
- ```
1425
-
1426
- Since we are already using [templates](#templates) to run our varOps and subscribe to changes, also the error message string subscribed to the operation result. In this example we would endue with the following messages.
1427
-
1428
- ```json
1429
- {
1430
- "errorMessages": {
1431
- "required": "Password is required",
1432
- "value": "Error value must be foo_bar"
1433
- }
1434
- }
1435
- ```
1436
-
1437
- PS: Don't's forget that we still have the default values provided with [templates](#templates) and the rules are the same
1438
-
1439
- #### Available VarOps
1440
-
1441
- - concatenate(arg1,arg2)
1442
- - add(arg1,arg2)
1443
- - subtract(arg1,arg2)
1444
-
1445
- ### Direct fields binding
1446
-
1447
- You can change multiple field values and properties with `bindFields` using the form ref in the react adapter, example:
1448
-
1449
- ```js
1450
- {
1451
- const ref = useRef < TFormRefActions > null;
1452
-
1453
- return (
1454
- <>
1455
- <Form id="form" ref={ref} schema={foo} />
1456
- </>
1457
- );
1458
- }
1459
-
1460
- const handleFields = (input1: string, input2: number) =>
1461
- ref.current?.bindFields({
1462
- input1: {
1463
- value: input1,
1464
- props: {
1465
- disabled: false,
1466
- },
1467
- },
1468
- input2: {
1469
- value: input2,
1470
- props: {
1471
- disabled: true,
1472
- },
1473
- },
1474
- });
1475
- ```
1476
-
1477
- All schema fields that has the same name as the passed keys will have his values/properties changed and validations executed
1478
-
1479
- > Also, you can listen to the `ON_FIELD_BINDED` event to execute any handler on the target field.
1480
-
1481
- ## State
1482
-
1483
- This key will allow you to set up some initial state on the field.
1484
-
1485
- ### hidden
1486
-
1487
- Hidden prop on state, will turn your field visible or invisible
1488
-
1489
- ```json
1490
- {
1491
- "state": {
1492
- "hidden": true
1493
- }
1494
- }
1495
- ```
1496
-
1497
- This will be reflected on the field scope.
1498
-
1499
- ### ignoreValue
1500
-
1501
- Ignore component value prop on state, will control whether the property with the formatted value will be created.
1502
-
1503
- ```json
1504
- {
1505
- "state": {
1506
- "ignoreValue": true
1507
- }
1508
- }
1509
- ```
1510
-
1511
- Very useful when using group ownership, to limit who will actually send the value.
1512
-
1513
- ## Rehydrate
1514
-
1515
- **DEPRECATED, you can accomplish it with templating (previous section)**
1516
-
1517
- It lets you rehydrate a given field
1518
-
1519
- ```json
1520
- {
1521
- "rehydrate": {
1522
- "ON_FIELD_CHANGE": [
1523
- {
1524
- "validations": {
1525
- "required": true
1526
- },
1527
- "fields": ["destination"]
1528
- }
1529
- ]
1530
- },
1531
- "component": "dropdown",
1532
- "name": "originalField"
1533
- }
1534
- ```
1535
-
1536
- The api is pretty much like visibility conditions. The above example will rehydrate the `destination` field when field with the directive (_originalField_) meets the validations configured
1537
-
1538
- ## Group
1539
-
1540
- In form, we can correlate fields into a single field name. This is called the group functionality.
1541
-
1542
- Say you have two checkboxes and want the selected value. You can use `group` for that
1543
-
1544
- ```json
1545
- [
1546
- {
1547
- "name": "checkOne",
1548
- "group": "checkedGroup",
1549
- "component": "checkbox",
1550
- "props": {
1551
- //...
1552
- }
1553
- },
1554
- {
1555
- "name": "checkTwo",
1556
- "group": "checkedGroup",
1557
- "component": "checkbox",
1558
- "props": {
1559
- //...
1560
- }
1561
- }
1562
- ]
1563
- ```
1564
-
1565
- This example will store the selected value of the checkbox in the `checkedGroup` and will then be sent to the client.
1566
-
1567
- ## Form Step
1568
-
1569
- In the form it is possible to use it as steps. With this it is possible to have more than one form in just one schema.
1570
-
1571
- For example, if you implement something like:
1572
-
1573
- ```js
1574
- {
1575
- components: [
1576
- { component: '', name: 'step1', children: [] },
1577
- { component: '', name: 'step2', children: [] },
1578
- { component: '', name: 'step3', children: [] },
1579
- ];
1580
- }
1581
- ```
1582
-
1583
- You can control the go back and forth event from the [onClick](#props) event of a button inside one of the forms using the form reference.
1584
- Or Simply using the form reference in a button outside the form, for example:
1585
-
1586
- ```js
1587
- {
1588
- const ref = useRef < TFormRefActions > null;
1589
-
1590
- return (
1591
- <Form id="form" ref={ref} onClick={() => ref.current?.stepForward()} />
1592
- );
1593
- }
1594
-
1595
- // --------------------- OR --------------------- //
1596
-
1597
- {
1598
- const ref = useRef < TFormRefActions > null;
1599
-
1600
- return (
1601
- <>
1602
- <Form id="form" ref={ref} />
1603
- <button onClick={ref.current?.stepBack()} />
1604
- </>
1605
- );
1606
- }
1607
- ```
1608
-
1609
- However, it is possible to choose which step you want to go or go back, using the numerical index or simply the name of the step you want, for example:
1610
-
1611
- ```js
1612
- () => ref.current?.stepForward(2);
1613
- // --------------- OR -------------- //
1614
- () => ref.current?.stepForward('step3');
1615
-
1616
- () => ref.current?.stepBack(0);
1617
- // --------------- OR -------------- //
1618
- () => ref.current?.stepBack('step1');
1619
- ```
1620
-
1621
- Additionally, you can use a `step` method provided by form reference to easily set a desired step using the `onFormMount` event. For example:
1622
-
1623
- ```js
1624
- <Form ref={ref} schema={schema} onFormMount={() => ref.current?.step(1)} />
1625
- ```
1626
-
1627
- Remembering that this method has a mandatory index parameter, which can either be the step index number in the array or simply its defined string name in the schema.
1628
-
1629
- # React Components
3
+ This is a react adapter to be used with form engine.
1630
4
 
1631
5
  ## React `<FormProvider />`
1632
6