@formio/js 5.0.0-dev.5896.56bf2bd → 5.0.0-dev.5902.1eb1690
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/Changelog.md +307 -10
- package/dist/formio.form.js +602 -590
- package/dist/formio.form.min.js +1 -1
- package/dist/formio.form.min.js.LICENSE.txt +2 -2
- package/dist/formio.full.js +604 -592
- package/dist/formio.full.min.js +1 -1
- package/dist/formio.full.min.js.LICENSE.txt +2 -2
- package/dist/formio.js +3131 -209
- package/dist/formio.min.js +1 -1
- package/dist/formio.min.js.LICENSE.txt +14 -0
- package/dist/formio.utils.js +58 -46
- package/dist/formio.utils.min.js +1 -1
- package/dist/formio.utils.min.js.LICENSE.txt +2 -2
- package/lib/cjs/Webform.d.ts +1 -1
- package/lib/cjs/Webform.js +27 -28
- package/lib/cjs/WebformBuilder.js +26 -35
- package/lib/cjs/Wizard.d.ts +0 -1
- package/lib/cjs/Wizard.js +19 -33
- package/lib/cjs/components/Components.d.ts +0 -7
- package/lib/cjs/components/Components.js +1 -33
- package/lib/cjs/components/_classes/component/Component.d.ts +39 -7
- package/lib/cjs/components/_classes/component/Component.js +106 -37
- package/lib/cjs/components/_classes/component/editForm/Component.edit.data.js +2 -2
- package/lib/cjs/components/_classes/component/editForm/Component.edit.validation.js +1 -1
- package/lib/cjs/components/_classes/componentModal/ComponentModal.d.ts +1 -0
- package/lib/cjs/components/_classes/componentModal/ComponentModal.js +1 -0
- package/lib/cjs/components/_classes/nested/NestedComponent.d.ts +4 -19
- package/lib/cjs/components/_classes/nested/NestedComponent.js +54 -60
- package/lib/cjs/components/_classes/nestedarray/NestedArrayComponent.d.ts +2 -1
- package/lib/cjs/components/_classes/nestedarray/NestedArrayComponent.js +9 -46
- package/lib/cjs/components/datagrid/DataGrid.d.ts +0 -1
- package/lib/cjs/components/datagrid/DataGrid.js +1 -45
- package/lib/cjs/components/datamap/DataMap.js +2 -3
- package/lib/cjs/components/editgrid/EditGrid.js +13 -13
- package/lib/cjs/components/form/Form.d.ts +1 -3
- package/lib/cjs/components/form/Form.js +20 -28
- package/lib/cjs/components/hidden/Hidden.d.ts +0 -1
- package/lib/cjs/components/hidden/Hidden.js +1 -1
- package/lib/cjs/components/html/HTML.js +15 -3
- package/lib/cjs/components/select/editForm/Select.edit.data.d.ts +1 -1
- package/lib/cjs/components/select/editForm/Select.edit.data.js +1 -0
- package/lib/cjs/components/selectboxes/SelectBoxes.js +8 -1
- package/lib/cjs/components/signature/Signature.js +3 -1
- package/lib/cjs/utils/conditionOperators/DateGreaterThan.js +2 -2
- package/lib/cjs/utils/conditionOperators/IsEmptyValue.d.ts +2 -2
- package/lib/cjs/utils/conditionOperators/IsEmptyValue.js +2 -2
- package/lib/cjs/utils/conditionOperators/IsEqualTo.d.ts +2 -2
- package/lib/cjs/utils/conditionOperators/IsEqualTo.js +2 -2
- package/lib/cjs/utils/formUtils.d.ts +25 -14
- package/lib/cjs/utils/formUtils.js +11 -16
- package/lib/cjs/utils/i18n.js +5 -0
- package/lib/cjs/utils/utils.d.ts +1 -2
- package/lib/cjs/utils/utils.js +19 -35
- package/lib/mjs/Webform.d.ts +1 -1
- package/lib/mjs/Webform.js +24 -27
- package/lib/mjs/WebformBuilder.js +26 -35
- package/lib/mjs/Wizard.d.ts +0 -1
- package/lib/mjs/Wizard.js +16 -29
- package/lib/mjs/components/Components.d.ts +0 -7
- package/lib/mjs/components/Components.js +1 -32
- package/lib/mjs/components/_classes/component/Component.d.ts +39 -7
- package/lib/mjs/components/_classes/component/Component.js +108 -38
- package/lib/mjs/components/_classes/component/editForm/Component.edit.data.js +2 -2
- package/lib/mjs/components/_classes/component/editForm/Component.edit.validation.js +1 -1
- package/lib/mjs/components/_classes/componentModal/ComponentModal.d.ts +1 -0
- package/lib/mjs/components/_classes/componentModal/ComponentModal.js +1 -0
- package/lib/mjs/components/_classes/nested/NestedComponent.d.ts +4 -19
- package/lib/mjs/components/_classes/nested/NestedComponent.js +55 -61
- package/lib/mjs/components/_classes/nestedarray/NestedArrayComponent.d.ts +2 -1
- package/lib/mjs/components/_classes/nestedarray/NestedArrayComponent.js +8 -43
- package/lib/mjs/components/datagrid/DataGrid.d.ts +0 -1
- package/lib/mjs/components/datagrid/DataGrid.js +1 -45
- package/lib/mjs/components/datamap/DataMap.js +2 -3
- package/lib/mjs/components/editgrid/EditGrid.js +15 -12
- package/lib/mjs/components/form/Form.d.ts +1 -3
- package/lib/mjs/components/form/Form.js +21 -28
- package/lib/mjs/components/hidden/Hidden.d.ts +0 -1
- package/lib/mjs/components/hidden/Hidden.js +1 -1
- package/lib/mjs/components/html/HTML.js +15 -3
- package/lib/mjs/components/select/editForm/Select.edit.data.d.ts +1 -1
- package/lib/mjs/components/select/editForm/Select.edit.data.js +1 -0
- package/lib/mjs/components/selectboxes/SelectBoxes.js +8 -1
- package/lib/mjs/components/signature/Signature.js +3 -1
- package/lib/mjs/utils/conditionOperators/DateGreaterThan.js +2 -2
- package/lib/mjs/utils/conditionOperators/IsEmptyValue.d.ts +2 -2
- package/lib/mjs/utils/conditionOperators/IsEmptyValue.js +2 -2
- package/lib/mjs/utils/conditionOperators/IsEqualTo.d.ts +2 -2
- package/lib/mjs/utils/conditionOperators/IsEqualTo.js +2 -2
- package/lib/mjs/utils/formUtils.d.ts +25 -14
- package/lib/mjs/utils/formUtils.js +2 -12
- package/lib/mjs/utils/i18n.js +4 -0
- package/lib/mjs/utils/utils.d.ts +1 -2
- package/lib/mjs/utils/utils.js +18 -33
- package/package.json +4 -4
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import Component from './_classes/component/Component';
|
|
2
2
|
import EditFormUtils from './_classes/component/editForm/utils';
|
|
3
3
|
import BaseEditForm from './_classes/component/Component.form';
|
|
4
|
-
import { getComponentKey, getModelType } from '../utils/utils';
|
|
5
4
|
import _ from 'lodash';
|
|
6
5
|
export default class Components {
|
|
7
6
|
static _editFormUtils = EditFormUtils;
|
|
@@ -46,34 +45,6 @@ export default class Components {
|
|
|
46
45
|
static setComponent(name, comp) {
|
|
47
46
|
Components.components[name] = comp;
|
|
48
47
|
}
|
|
49
|
-
/**
|
|
50
|
-
* Return a path of component's value.
|
|
51
|
-
* @param {Component} component - The component instance.
|
|
52
|
-
* @returns {string} - The component's value path.
|
|
53
|
-
*/
|
|
54
|
-
static getComponentPath(component) {
|
|
55
|
-
let path = '';
|
|
56
|
-
const componentKey = getComponentKey(component.component);
|
|
57
|
-
if (componentKey) {
|
|
58
|
-
let thisPath = component.options?.parent || component;
|
|
59
|
-
while (thisPath && !thisPath.allowData && thisPath.parent) {
|
|
60
|
-
thisPath = thisPath.parent;
|
|
61
|
-
}
|
|
62
|
-
// TODO: any component that is nested in e.g. a Data Grid or an Edit Grid is going to receive a row prop; the problem
|
|
63
|
-
// is that options.row is passed to each further nested component, which results in erroneous paths like
|
|
64
|
-
// `editGrid[0].container[0].textField` rather than `editGrid[0].container.textField`. This should be adapted for other
|
|
65
|
-
// components with a tree-like data model
|
|
66
|
-
const rowIndex = component.row;
|
|
67
|
-
const rowIndexPath = rowIndex && !['container'].includes(thisPath.component.type) ? `[${Number.parseInt(rowIndex)}]` : '';
|
|
68
|
-
path = `${thisPath.path}${rowIndexPath}.`;
|
|
69
|
-
if (rowIndexPath && getModelType(thisPath) === 'nestedDataArray') {
|
|
70
|
-
path = `${path}data.`;
|
|
71
|
-
}
|
|
72
|
-
path += componentKey;
|
|
73
|
-
return _.trim(path, '.');
|
|
74
|
-
}
|
|
75
|
-
return path;
|
|
76
|
-
}
|
|
77
48
|
static create(component, options, data) {
|
|
78
49
|
let comp = null;
|
|
79
50
|
if (component.type && Components.components.hasOwnProperty(component.type)) {
|
|
@@ -98,9 +69,7 @@ export default class Components {
|
|
|
98
69
|
else {
|
|
99
70
|
comp = new Component(component, options, data);
|
|
100
71
|
}
|
|
101
|
-
|
|
102
|
-
if (path) {
|
|
103
|
-
comp.path = path;
|
|
72
|
+
if (comp.path) {
|
|
104
73
|
comp.componentsMap[comp.path] = comp;
|
|
105
74
|
}
|
|
106
75
|
return comp;
|
|
@@ -42,14 +42,13 @@ declare class Component extends Element {
|
|
|
42
42
|
*/
|
|
43
43
|
private _hasCondition;
|
|
44
44
|
/**
|
|
45
|
-
*
|
|
45
|
+
* The row index for this component.
|
|
46
46
|
*/
|
|
47
|
-
|
|
47
|
+
_rowIndex: number | undefined;
|
|
48
48
|
/**
|
|
49
|
-
*
|
|
50
|
-
* @type {string}
|
|
49
|
+
* References to dom elements
|
|
51
50
|
*/
|
|
52
|
-
|
|
51
|
+
refs: {};
|
|
53
52
|
/**
|
|
54
53
|
* An array of all the children components errors.
|
|
55
54
|
*/
|
|
@@ -114,7 +113,19 @@ declare class Component extends Element {
|
|
|
114
113
|
* @type {Component}
|
|
115
114
|
*/
|
|
116
115
|
parent: Component;
|
|
116
|
+
/**
|
|
117
|
+
* The component paths for this component.
|
|
118
|
+
* @type {import('@formio/core').ComponentPaths} - The component paths.
|
|
119
|
+
*/
|
|
120
|
+
paths: import('@formio/core').ComponentPaths;
|
|
117
121
|
_path: string;
|
|
122
|
+
/**
|
|
123
|
+
* Determines if this component is conditionally hidden. Should generally not be set outside of conditional logic pipeline.
|
|
124
|
+
* This is necessary because of clearOnHide behavior that only clears when conditionally hidden - we need to track
|
|
125
|
+
* conditionallyHidden separately from "regular" visibility.
|
|
126
|
+
*/
|
|
127
|
+
_parentConditionallyHidden: any;
|
|
128
|
+
_conditionallyHidden: any;
|
|
118
129
|
/**
|
|
119
130
|
* Determines if this component is visible, or not.
|
|
120
131
|
*/
|
|
@@ -158,7 +169,7 @@ declare class Component extends Element {
|
|
|
158
169
|
* @type {*}
|
|
159
170
|
*/
|
|
160
171
|
info: any;
|
|
161
|
-
get componentsMap():
|
|
172
|
+
get componentsMap(): object;
|
|
162
173
|
set data(value: any);
|
|
163
174
|
get data(): any;
|
|
164
175
|
mergeSchema(component?: {}): any;
|
|
@@ -182,6 +193,17 @@ declare class Component extends Element {
|
|
|
182
193
|
* @returns {boolean} - TRUE if the component is disabled.
|
|
183
194
|
*/
|
|
184
195
|
get disabled(): boolean;
|
|
196
|
+
/**
|
|
197
|
+
* Set Row Index to row and update each component.
|
|
198
|
+
* @param {number} value - The row index.
|
|
199
|
+
* @returns {void}
|
|
200
|
+
*/
|
|
201
|
+
set rowIndex(value: number);
|
|
202
|
+
/**
|
|
203
|
+
* Get Row Index.
|
|
204
|
+
* @returns {number} - The row index.
|
|
205
|
+
*/
|
|
206
|
+
get rowIndex(): number;
|
|
185
207
|
afterComponentAssign(): void;
|
|
186
208
|
createAddon(addonConfiguration: any): any;
|
|
187
209
|
get shouldDisabled(): any;
|
|
@@ -190,6 +212,8 @@ declare class Component extends Element {
|
|
|
190
212
|
get hasInput(): any;
|
|
191
213
|
get defaultSchema(): any;
|
|
192
214
|
get key(): any;
|
|
215
|
+
set path(path: string | undefined);
|
|
216
|
+
get path(): string | undefined;
|
|
193
217
|
set parentVisible(value: any);
|
|
194
218
|
get parentVisible(): any;
|
|
195
219
|
set parentDisabled(value: boolean);
|
|
@@ -207,12 +231,20 @@ declare class Component extends Element {
|
|
|
207
231
|
* @returns {boolean} - Whether the component is visible or not.
|
|
208
232
|
*/
|
|
209
233
|
get visible(): boolean;
|
|
234
|
+
get conditionallyHidden(): any;
|
|
235
|
+
/**
|
|
236
|
+
* Evaluates whether the component is conditionally hidden (as opposed to intentionally hidden, e.g. via the `hidden` component schema property).
|
|
237
|
+
* @param {object} data - The data object to evaluate the condition against.
|
|
238
|
+
* @param {object} row - The row object to evaluate the condition against.
|
|
239
|
+
* @returns {boolean} - Whether the component is conditionally hidden.
|
|
240
|
+
*/
|
|
241
|
+
checkConditionallyHidden(data?: object, row?: object): boolean;
|
|
210
242
|
set currentForm(instance: any);
|
|
211
243
|
get currentForm(): any;
|
|
212
244
|
_currentForm: any;
|
|
213
245
|
get fullMode(): boolean;
|
|
214
246
|
get builderMode(): boolean;
|
|
215
|
-
get calculatedPath(): string;
|
|
247
|
+
get calculatedPath(): string | undefined;
|
|
216
248
|
get labelPosition(): any;
|
|
217
249
|
get labelWidth(): any;
|
|
218
250
|
get labelMargin(): any;
|
|
@@ -6,7 +6,7 @@ import isMobile from 'ismobilejs';
|
|
|
6
6
|
import { processOne, processOneSync, validateProcessInfo } from '@formio/core/process';
|
|
7
7
|
import { Formio } from '../../../Formio';
|
|
8
8
|
import * as FormioUtils from '../../../utils/utils';
|
|
9
|
-
import { fastCloneDeep, boolValue,
|
|
9
|
+
import { fastCloneDeep, boolValue, isInsideScopingComponent, currentTimezone, getScriptPlugin, getContextualRowData } from '../../../utils/utils';
|
|
10
10
|
import Element from '../../../Element';
|
|
11
11
|
import ComponentModal from '../componentModal/ComponentModal';
|
|
12
12
|
import Widgets from '../../../widgets';
|
|
@@ -221,6 +221,10 @@ export default class Component extends Element {
|
|
|
221
221
|
* @private
|
|
222
222
|
*/
|
|
223
223
|
this._hasCondition = null;
|
|
224
|
+
/**
|
|
225
|
+
* The row index for this component.
|
|
226
|
+
*/
|
|
227
|
+
this._rowIndex = undefined;
|
|
224
228
|
/**
|
|
225
229
|
* References to dom elements
|
|
226
230
|
*/
|
|
@@ -231,11 +235,6 @@ export default class Component extends Element {
|
|
|
231
235
|
this.options.components[component.type]) {
|
|
232
236
|
_.merge(component, this.options.components[component.type]);
|
|
233
237
|
}
|
|
234
|
-
/**
|
|
235
|
-
* The data path to this specific component instance.
|
|
236
|
-
* @type {string}
|
|
237
|
-
*/
|
|
238
|
-
this.path = component?.key || '';
|
|
239
238
|
/**
|
|
240
239
|
* An array of all the children components errors.
|
|
241
240
|
*/
|
|
@@ -304,15 +303,30 @@ export default class Component extends Element {
|
|
|
304
303
|
* @type {Component}
|
|
305
304
|
*/
|
|
306
305
|
this.parent = this.options.parent;
|
|
306
|
+
/**
|
|
307
|
+
* The component paths for this component.
|
|
308
|
+
* @type {import('@formio/core').ComponentPaths} - The component paths.
|
|
309
|
+
*/
|
|
310
|
+
this.paths = FormioUtils.getComponentPaths(this.component, this.parent?.component, {
|
|
311
|
+
...this.parent?.paths,
|
|
312
|
+
dataIndex: this.options.rowIndex === undefined ? this.parent?.paths?.dataIndex : this.options.rowIndex
|
|
313
|
+
});
|
|
307
314
|
this.options.name = this.options.name || 'data';
|
|
308
315
|
this._path = '';
|
|
309
316
|
// Needs for Nextgen Rules Engine
|
|
310
317
|
this.resetCaches();
|
|
318
|
+
/**
|
|
319
|
+
* Determines if this component is conditionally hidden. Should generally not be set outside of conditional logic pipeline.
|
|
320
|
+
* This is necessary because of clearOnHide behavior that only clears when conditionally hidden - we need to track
|
|
321
|
+
* conditionallyHidden separately from "regular" visibility.
|
|
322
|
+
*/
|
|
323
|
+
this._parentConditionallyHidden = this.options.hasOwnProperty('parentConditionallyHidden') ? this.options.parentConditionallyHidden : false;
|
|
324
|
+
this._conditionallyHidden = this.checkConditionallyHidden(null, data) || this._parentConditionallyHidden;
|
|
311
325
|
/**
|
|
312
326
|
* Determines if this component is visible, or not.
|
|
313
327
|
*/
|
|
314
328
|
this._parentVisible = this.options.hasOwnProperty('parentVisible') ? this.options.parentVisible : true;
|
|
315
|
-
this._visible = this._parentVisible && this.
|
|
329
|
+
this._visible = this._parentVisible && (this.hasCondition() ? !this._conditionallyHidden : !this.component.hidden);
|
|
316
330
|
this._parentDisabled = false;
|
|
317
331
|
/**
|
|
318
332
|
* The reference attribute name for this component
|
|
@@ -381,7 +395,7 @@ export default class Component extends Element {
|
|
|
381
395
|
if (this.allowData && this.key) {
|
|
382
396
|
this.options.name += `[${this.key}]`;
|
|
383
397
|
// If component is visible or not set to clear on hide, set the default value.
|
|
384
|
-
if (this.
|
|
398
|
+
if (!(this.conditionallyHidden && this.component.clearOnHide)) {
|
|
385
399
|
if (!this.hasValue()) {
|
|
386
400
|
if (this.shouldAddDefaultValue) {
|
|
387
401
|
this.dataValue = this.defaultValue;
|
|
@@ -409,12 +423,7 @@ export default class Component extends Element {
|
|
|
409
423
|
}
|
|
410
424
|
/* eslint-enable max-statements */
|
|
411
425
|
get componentsMap() {
|
|
412
|
-
|
|
413
|
-
return this.localRoot.childComponentsMap;
|
|
414
|
-
}
|
|
415
|
-
const localMap = {};
|
|
416
|
-
localMap[this.path] = this;
|
|
417
|
-
return localMap;
|
|
426
|
+
return this.root?.childComponentsMap || {};
|
|
418
427
|
}
|
|
419
428
|
get data() {
|
|
420
429
|
return this._data;
|
|
@@ -455,11 +464,31 @@ export default class Component extends Element {
|
|
|
455
464
|
}
|
|
456
465
|
init() {
|
|
457
466
|
this.disabled = this.shouldDisabled;
|
|
458
|
-
this.
|
|
467
|
+
this._conditionallyHidden = this.checkConditionallyHidden();
|
|
468
|
+
this._visible = (this.hasCondition() ? !this.conditionallyHidden : !this.component.hidden);
|
|
459
469
|
if (this.component.addons?.length) {
|
|
460
470
|
this.component.addons.forEach((addon) => this.createAddon(addon));
|
|
461
471
|
}
|
|
462
472
|
}
|
|
473
|
+
/**
|
|
474
|
+
* Get Row Index.
|
|
475
|
+
* @returns {number} - The row index.
|
|
476
|
+
*/
|
|
477
|
+
get rowIndex() {
|
|
478
|
+
return this._rowIndex;
|
|
479
|
+
}
|
|
480
|
+
/**
|
|
481
|
+
* Set Row Index to row and update each component.
|
|
482
|
+
* @param {number} value - The row index.
|
|
483
|
+
* @returns {void}
|
|
484
|
+
*/
|
|
485
|
+
set rowIndex(value) {
|
|
486
|
+
this.paths = FormioUtils.getComponentPaths(this.component, this.parent?.component, {
|
|
487
|
+
...(this.parent?.paths || {}),
|
|
488
|
+
...{ dataIndex: value }
|
|
489
|
+
});
|
|
490
|
+
this._rowIndex = value;
|
|
491
|
+
}
|
|
463
492
|
afterComponentAssign() {
|
|
464
493
|
//implement in extended classes
|
|
465
494
|
}
|
|
@@ -528,6 +557,12 @@ export default class Component extends Element {
|
|
|
528
557
|
get key() {
|
|
529
558
|
return _.get(this.component, 'key', '');
|
|
530
559
|
}
|
|
560
|
+
get path() {
|
|
561
|
+
return this.paths.dataPath;
|
|
562
|
+
}
|
|
563
|
+
set path(path) {
|
|
564
|
+
throw new Error('Should not be setting the path of a component.');
|
|
565
|
+
}
|
|
531
566
|
set parentVisible(value) {
|
|
532
567
|
this._parentVisible = value;
|
|
533
568
|
}
|
|
@@ -573,7 +608,6 @@ export default class Component extends Element {
|
|
|
573
608
|
return;
|
|
574
609
|
}
|
|
575
610
|
this._visible = value;
|
|
576
|
-
this.clearOnHide();
|
|
577
611
|
this.redraw();
|
|
578
612
|
}
|
|
579
613
|
}
|
|
@@ -594,6 +628,21 @@ export default class Component extends Element {
|
|
|
594
628
|
}
|
|
595
629
|
return this._visible && this._parentVisible;
|
|
596
630
|
}
|
|
631
|
+
get conditionallyHidden() {
|
|
632
|
+
return this._conditionallyHidden || this._parentConditionallyHidden;
|
|
633
|
+
}
|
|
634
|
+
/**
|
|
635
|
+
* Evaluates whether the component is conditionally hidden (as opposed to intentionally hidden, e.g. via the `hidden` component schema property).
|
|
636
|
+
* @param {object} data - The data object to evaluate the condition against.
|
|
637
|
+
* @param {object} row - The row object to evaluate the condition against.
|
|
638
|
+
* @returns {boolean} - Whether the component is conditionally hidden.
|
|
639
|
+
*/
|
|
640
|
+
checkConditionallyHidden(data = null, row = null) {
|
|
641
|
+
if (!this.hasCondition()) {
|
|
642
|
+
return false;
|
|
643
|
+
}
|
|
644
|
+
return !this.conditionallyVisible(data, row);
|
|
645
|
+
}
|
|
597
646
|
get currentForm() {
|
|
598
647
|
return this._currentForm;
|
|
599
648
|
}
|
|
@@ -1246,7 +1295,7 @@ export default class Component extends Element {
|
|
|
1246
1295
|
if (refreshData === 'data') {
|
|
1247
1296
|
this.refresh(this.data, changed, flags);
|
|
1248
1297
|
}
|
|
1249
|
-
else if ((changePath &&
|
|
1298
|
+
else if ((changePath && (changed.instance?.paths?.localPath === refreshData)) && changed && changed.instance &&
|
|
1250
1299
|
// Make sure the changed component is not in a different "context". Solves issues where refreshOn being set
|
|
1251
1300
|
// in fields inside EditGrids could alter their state from other rows (which is bad).
|
|
1252
1301
|
this.inContext(changed.instance)) {
|
|
@@ -1764,7 +1813,7 @@ export default class Component extends Element {
|
|
|
1764
1813
|
rebuild() {
|
|
1765
1814
|
this.destroy();
|
|
1766
1815
|
this.init();
|
|
1767
|
-
this.visible = this.
|
|
1816
|
+
this.visible = this.hasCondition() ? !this.conditionallyHidden : !this.component.hidden;
|
|
1768
1817
|
return this.redraw();
|
|
1769
1818
|
}
|
|
1770
1819
|
/**
|
|
@@ -1831,8 +1880,8 @@ export default class Component extends Element {
|
|
|
1831
1880
|
conditionallyVisible(data, row) {
|
|
1832
1881
|
data = data || this.rootValue;
|
|
1833
1882
|
row = row || this.data;
|
|
1834
|
-
if (this.builderMode || this.previewMode
|
|
1835
|
-
return
|
|
1883
|
+
if (this.builderMode || this.previewMode) {
|
|
1884
|
+
return true;
|
|
1836
1885
|
}
|
|
1837
1886
|
data = data || (this.root ? this.root.data : {});
|
|
1838
1887
|
return this.checkCondition(row, data);
|
|
@@ -1862,8 +1911,14 @@ export default class Component extends Element {
|
|
|
1862
1911
|
if (!this.builderMode & !this.previewMode && this.fieldLogic(data, row)) {
|
|
1863
1912
|
this.redraw();
|
|
1864
1913
|
}
|
|
1865
|
-
// Check advanced conditions
|
|
1866
|
-
const
|
|
1914
|
+
// Check advanced conditions (and cache the result)
|
|
1915
|
+
const isConditionallyHidden = this.checkConditionallyHidden(data, row) || this._parentConditionallyHidden;
|
|
1916
|
+
if (isConditionallyHidden !== this._conditionallyHidden) {
|
|
1917
|
+
this._conditionallyHidden = isConditionallyHidden;
|
|
1918
|
+
this.clearOnHide();
|
|
1919
|
+
}
|
|
1920
|
+
// Check visibility
|
|
1921
|
+
const visible = (this.hasCondition() ? !this.conditionallyHidden : !this.component.hidden);
|
|
1867
1922
|
if (this.visible !== visible) {
|
|
1868
1923
|
this.visible = visible;
|
|
1869
1924
|
}
|
|
@@ -1973,6 +2028,12 @@ export default class Component extends Element {
|
|
|
1973
2028
|
FormioUtils.setActionProperty(newComponent, action, result, row, data, this);
|
|
1974
2029
|
const property = action.property.value;
|
|
1975
2030
|
if (!_.isEqual(_.get(this.component, property), _.get(newComponent, property))) {
|
|
2031
|
+
// Advanced Logic can modify the component's hidden property; because we track conditionally hidden state
|
|
2032
|
+
// separately from the component's hidden property, and technically this Advanced Logic conditionally hides
|
|
2033
|
+
// a component, we need to set _conditionallyHidden to the new value
|
|
2034
|
+
if (property === 'hidden') {
|
|
2035
|
+
this._conditionallyHidden = newComponent.hidden;
|
|
2036
|
+
}
|
|
1976
2037
|
changed = true;
|
|
1977
2038
|
}
|
|
1978
2039
|
break;
|
|
@@ -1986,7 +2047,7 @@ export default class Component extends Element {
|
|
|
1986
2047
|
component: newComponent,
|
|
1987
2048
|
result,
|
|
1988
2049
|
});
|
|
1989
|
-
if (!_.isEqual(oldValue, newValue) && !(this.component.clearOnHide &&
|
|
2050
|
+
if (!_.isEqual(oldValue, newValue) && !(this.component.clearOnHide && this.conditionallyHidden)) {
|
|
1990
2051
|
this.setValue(newValue);
|
|
1991
2052
|
if (this.viewOnly) {
|
|
1992
2053
|
this.dataValue = newValue;
|
|
@@ -2019,7 +2080,7 @@ export default class Component extends Element {
|
|
|
2019
2080
|
component: newComponent,
|
|
2020
2081
|
result,
|
|
2021
2082
|
}, 'value');
|
|
2022
|
-
if (!_.isEqual(oldValue, newValue) && !(this.component.clearOnHide &&
|
|
2083
|
+
if (!_.isEqual(oldValue, newValue) && !(this.component.clearOnHide && this.conditionallyHidden)) {
|
|
2023
2084
|
this.setValue(newValue);
|
|
2024
2085
|
if (this.viewOnly) {
|
|
2025
2086
|
this.dataValue = newValue;
|
|
@@ -2130,7 +2191,7 @@ export default class Component extends Element {
|
|
|
2130
2191
|
this.component.clearOnHide !== false &&
|
|
2131
2192
|
!this.options.readOnly &&
|
|
2132
2193
|
!this.options.showHiddenFields) {
|
|
2133
|
-
if (
|
|
2194
|
+
if (this.conditionallyHidden) {
|
|
2134
2195
|
this.deleteValue();
|
|
2135
2196
|
}
|
|
2136
2197
|
else if (!this.hasValue() && this.shouldAddDefaultValue) {
|
|
@@ -2392,7 +2453,7 @@ export default class Component extends Element {
|
|
|
2392
2453
|
*/
|
|
2393
2454
|
get dataValue() {
|
|
2394
2455
|
if (!this.key ||
|
|
2395
|
-
(
|
|
2456
|
+
(this.conditionallyHidden && this.component.clearOnHide && !this.rootPristine)) {
|
|
2396
2457
|
return this.emptyValue;
|
|
2397
2458
|
}
|
|
2398
2459
|
if (!this.hasValue() && this.shouldAddDefaultValue) {
|
|
@@ -2411,7 +2472,7 @@ export default class Component extends Element {
|
|
|
2411
2472
|
set dataValue(value) {
|
|
2412
2473
|
if (!this.allowData ||
|
|
2413
2474
|
!this.key ||
|
|
2414
|
-
(
|
|
2475
|
+
(this.conditionallyHidden && this.component.clearOnHide && !this.rootPristine)) {
|
|
2415
2476
|
return;
|
|
2416
2477
|
}
|
|
2417
2478
|
if ((value !== null) && (value !== undefined)) {
|
|
@@ -2482,7 +2543,7 @@ export default class Component extends Element {
|
|
|
2482
2543
|
}
|
|
2483
2544
|
return value;
|
|
2484
2545
|
};
|
|
2485
|
-
if (this.defaultMask) {
|
|
2546
|
+
if (Array.isArray(this.defaultMask) ? this.defaultMask.length > 0 : this.defaultMask) {
|
|
2486
2547
|
if (Array.isArray(defaultValue)) {
|
|
2487
2548
|
defaultValue = defaultValue.map(checkMask);
|
|
2488
2549
|
}
|
|
@@ -2731,7 +2792,7 @@ export default class Component extends Element {
|
|
|
2731
2792
|
// If no calculated value or
|
|
2732
2793
|
// hidden and set to clearOnHide (Don't calculate a value for a hidden field set to clear when hidden)
|
|
2733
2794
|
const { clearOnHide } = this.component;
|
|
2734
|
-
const shouldBeCleared =
|
|
2795
|
+
const shouldBeCleared = this.conditionallyHidden && clearOnHide;
|
|
2735
2796
|
const allowOverride = _.get(this.component, 'allowCalculateOverride', false);
|
|
2736
2797
|
if (shouldBeCleared) {
|
|
2737
2798
|
// remove calculated value so that the value is recalculated once component becomes visible
|
|
@@ -2857,6 +2918,9 @@ export default class Component extends Element {
|
|
|
2857
2918
|
* @returns {string} - The message to show when the component is invalid.
|
|
2858
2919
|
*/
|
|
2859
2920
|
invalidMessage(data, dirty, ignoreCondition, row) {
|
|
2921
|
+
if (!row) {
|
|
2922
|
+
row = getContextualRowData(this.component, data, this.paths);
|
|
2923
|
+
}
|
|
2860
2924
|
if (!ignoreCondition && !this.checkCondition(row, data)) {
|
|
2861
2925
|
return '';
|
|
2862
2926
|
}
|
|
@@ -2874,6 +2938,8 @@ export default class Component extends Element {
|
|
|
2874
2938
|
data,
|
|
2875
2939
|
row,
|
|
2876
2940
|
path: this.path || this.component.key,
|
|
2941
|
+
parent: this.parent?.component,
|
|
2942
|
+
paths: this.paths,
|
|
2877
2943
|
scope: validationScope,
|
|
2878
2944
|
instance: this,
|
|
2879
2945
|
processors: [
|
|
@@ -2926,7 +2992,7 @@ export default class Component extends Element {
|
|
|
2926
2992
|
if (flags.silentCheck) {
|
|
2927
2993
|
return [];
|
|
2928
2994
|
}
|
|
2929
|
-
let isDirty = this.dirty || flags.dirty;
|
|
2995
|
+
let isDirty = (flags.dirty === false) ? false : (this.dirty || flags.dirty);
|
|
2930
2996
|
if (this.options.alwaysDirty) {
|
|
2931
2997
|
isDirty = true;
|
|
2932
2998
|
}
|
|
@@ -2951,7 +3017,10 @@ export default class Component extends Element {
|
|
|
2951
3017
|
component: this.component,
|
|
2952
3018
|
data,
|
|
2953
3019
|
row,
|
|
3020
|
+
local: !!flags.local,
|
|
2954
3021
|
value: this.validationValue,
|
|
3022
|
+
parent: this.parent?.component,
|
|
3023
|
+
paths: this.paths,
|
|
2955
3024
|
path: this.path || this.component.key,
|
|
2956
3025
|
instance: this,
|
|
2957
3026
|
form: this.root ? this.root._form : {},
|
|
@@ -3214,12 +3283,6 @@ export default class Component extends Element {
|
|
|
3214
3283
|
return (this.component.protected || !this.component.persistent || (this.component.persistent === 'client-only'));
|
|
3215
3284
|
}
|
|
3216
3285
|
shouldSkipValidation(data, row, flags = {}) {
|
|
3217
|
-
const { validateWhenHidden = false } = this.component || {};
|
|
3218
|
-
const forceValidOnHidden = (!this.visible || !this.checkCondition(row, data)) && !validateWhenHidden;
|
|
3219
|
-
if (forceValidOnHidden) {
|
|
3220
|
-
// If this component is forced valid when it is hidden, then we also need to reset the errors for this component.
|
|
3221
|
-
this._errors = [];
|
|
3222
|
-
}
|
|
3223
3286
|
const rules = [
|
|
3224
3287
|
// Do not validate if the flags say not too.
|
|
3225
3288
|
() => flags.noValidate,
|
|
@@ -3230,7 +3293,14 @@ export default class Component extends Element {
|
|
|
3230
3293
|
// Check to see if we are editing and if so, check component persistence.
|
|
3231
3294
|
() => this.isValueHidden(),
|
|
3232
3295
|
// Force valid if component is hidden.
|
|
3233
|
-
() =>
|
|
3296
|
+
() => {
|
|
3297
|
+
if (!this.component.validateWhenHidden && (!this.visible || !this.checkCondition(row, data))) {
|
|
3298
|
+
// If this component is forced valid when it is hidden, then we also need to reset the errors for this component.
|
|
3299
|
+
this._errors = [];
|
|
3300
|
+
return true;
|
|
3301
|
+
}
|
|
3302
|
+
return false;
|
|
3303
|
+
}
|
|
3234
3304
|
];
|
|
3235
3305
|
return rules.some(pred => pred());
|
|
3236
3306
|
}
|
|
@@ -3367,7 +3437,7 @@ export default class Component extends Element {
|
|
|
3367
3437
|
// If component definition changed, replace it.
|
|
3368
3438
|
if (!_.isEqual(this.component, newComponent)) {
|
|
3369
3439
|
this.component = newComponent;
|
|
3370
|
-
const visible = this.
|
|
3440
|
+
const visible = this.hasCondition() ? !this.conditionallyHidden : !this.component.hidden;
|
|
3371
3441
|
const disabled = this.shouldDisabled;
|
|
3372
3442
|
// Change states which won't be recalculated during redrawing
|
|
3373
3443
|
if (this.visible !== visible) {
|
|
@@ -128,10 +128,10 @@ export default [
|
|
|
128
128
|
{
|
|
129
129
|
weight: 700,
|
|
130
130
|
type: 'checkbox',
|
|
131
|
-
label: '
|
|
131
|
+
label: 'Omit Value From Submission Data When Conditionally Hidden',
|
|
132
132
|
key: 'clearOnHide',
|
|
133
133
|
defaultValue: true,
|
|
134
|
-
tooltip: 'When a field is hidden,
|
|
134
|
+
tooltip: 'When a field is conditionally hidden, omit the value from the submission data.',
|
|
135
135
|
input: true
|
|
136
136
|
},
|
|
137
137
|
EditFormUtils.javaScriptValue('Custom Default Value', 'customDefaultValue', 'customDefaultValue', 1000, '<p><h4>Example:</h4><pre>value = data.firstName + " " + data.lastName;</pre></p>', '<p><h4>Example:</h4><pre>{"cat": [{"var": "data.firstName"}, " ", {"var": "data.lastName"}]}</pre>'),
|
|
@@ -22,7 +22,7 @@ export default [
|
|
|
22
22
|
weight: 100,
|
|
23
23
|
type: 'checkbox',
|
|
24
24
|
label: 'Validate When Hidden',
|
|
25
|
-
tooltip: 'Validates the component when it is hidden/conditionally hidden. Vaildation errors are displayed in the error alert on the form submission.',
|
|
25
|
+
tooltip: 'Validates the component when it is hidden/conditionally hidden. Vaildation errors are displayed in the error alert on the form submission. Use caution when enabling this setting, as it can cause a hidden component to be invalid with no way for the form user to correct it.',
|
|
26
26
|
key: 'validateWhenHidden',
|
|
27
27
|
input: true
|
|
28
28
|
},
|
|
@@ -56,18 +56,6 @@ export default class NestedComponent extends Field {
|
|
|
56
56
|
* @returns {object} - The current form object.
|
|
57
57
|
*/
|
|
58
58
|
get currentForm(): object;
|
|
59
|
-
/**
|
|
60
|
-
* Set Row Index to row and update each component.
|
|
61
|
-
* @param {number} value - The row index.
|
|
62
|
-
* @returns {void}
|
|
63
|
-
*/
|
|
64
|
-
set rowIndex(value: number);
|
|
65
|
-
/**
|
|
66
|
-
* Get Row Index.
|
|
67
|
-
* @returns {number} - The row index.
|
|
68
|
-
*/
|
|
69
|
-
get rowIndex(): number;
|
|
70
|
-
_rowIndex: number | undefined;
|
|
71
59
|
/**
|
|
72
60
|
* Get Contextual data of the component.
|
|
73
61
|
* @returns {object} - The contextual data of the component.
|
|
@@ -115,14 +103,11 @@ export default class NestedComponent extends Field {
|
|
|
115
103
|
*/
|
|
116
104
|
eachComponent(fn: Function): void;
|
|
117
105
|
/**
|
|
118
|
-
* Returns a component provided a key. This performs a deep search within the
|
|
119
|
-
* component tree.
|
|
106
|
+
* Returns a component provided a key. This performs a deep search within the component tree.
|
|
120
107
|
* @param {string} path - The path to the component.
|
|
121
|
-
* @param {Function} [fn] - Called with the component once found.
|
|
122
|
-
* @param {string} [originalPath] - The original path to the component.
|
|
123
108
|
* @returns {any} - The component that is located.
|
|
124
109
|
*/
|
|
125
|
-
getComponent(path: string
|
|
110
|
+
getComponent(path: string): any;
|
|
126
111
|
/**
|
|
127
112
|
* Return a component provided the Id of the component.
|
|
128
113
|
* @param {string} id - The Id of the component.
|
|
@@ -211,12 +196,12 @@ export default class NestedComponent extends Field {
|
|
|
211
196
|
calculateValue(data: any, flags: any, row: any): any;
|
|
212
197
|
isLastPage(): boolean;
|
|
213
198
|
isValid(data: any, dirty: any): any;
|
|
214
|
-
validationProcessor({ scope, data, row, instance,
|
|
199
|
+
validationProcessor({ scope, data, row, instance, paths }: {
|
|
215
200
|
scope: any;
|
|
216
201
|
data: any;
|
|
217
202
|
row: any;
|
|
218
203
|
instance: any;
|
|
219
|
-
|
|
204
|
+
paths: any;
|
|
220
205
|
}, flags: any): void;
|
|
221
206
|
/**
|
|
222
207
|
* Perform a validation on all child components of this nested component.
|