@formio/js 5.0.0-dev.5947.acce78f → 5.0.0-dev.5948.072adfa
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/dist/formio.form.js +9 -9
- package/dist/formio.form.min.js +1 -1
- package/dist/formio.full.js +9 -9
- package/dist/formio.full.min.js +1 -1
- package/lib/cjs/components/_classes/component/Component.d.ts +15 -0
- package/lib/cjs/components/_classes/component/Component.js +50 -16
- package/lib/cjs/components/_classes/component/editForm/Component.edit.data.js +2 -2
- package/lib/cjs/components/_classes/nested/NestedComponent.js +16 -7
- package/lib/cjs/components/datamap/DataMap.js +1 -1
- package/lib/cjs/components/editgrid/EditGrid.d.ts +1 -1
- package/lib/cjs/components/editgrid/EditGrid.js +9 -7
- package/lib/cjs/components/form/Form.js +5 -4
- package/lib/cjs/components/html/HTML.js +15 -3
- package/lib/cjs/formio.form.js +1 -0
- package/lib/mjs/components/_classes/component/Component.d.ts +15 -0
- package/lib/mjs/components/_classes/component/Component.js +50 -16
- package/lib/mjs/components/_classes/component/editForm/Component.edit.data.js +2 -2
- package/lib/mjs/components/_classes/nested/NestedComponent.js +16 -7
- package/lib/mjs/components/datamap/DataMap.js +1 -1
- package/lib/mjs/components/editgrid/EditGrid.d.ts +1 -1
- package/lib/mjs/components/editgrid/EditGrid.js +9 -7
- package/lib/mjs/components/form/Form.js +5 -4
- package/lib/mjs/components/html/HTML.js +15 -3
- package/lib/mjs/formio.form.js +1 -0
- package/package.json +2 -2
@@ -119,6 +119,13 @@ declare class Component extends Element {
|
|
119
119
|
*/
|
120
120
|
paths: import('@formio/core').ComponentPaths;
|
121
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;
|
122
129
|
/**
|
123
130
|
* Determines if this component is visible, or not.
|
124
131
|
*/
|
@@ -224,6 +231,14 @@ declare class Component extends Element {
|
|
224
231
|
* @returns {boolean} - Whether the component is visible or not.
|
225
232
|
*/
|
226
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;
|
227
242
|
set currentForm(instance: any);
|
228
243
|
get currentForm(): any;
|
229
244
|
_currentForm: any;
|
@@ -350,11 +350,18 @@ class Component extends Element_1.default {
|
|
350
350
|
this._path = '';
|
351
351
|
// Needs for Nextgen Rules Engine
|
352
352
|
this.resetCaches();
|
353
|
+
/**
|
354
|
+
* Determines if this component is conditionally hidden. Should generally not be set outside of conditional logic pipeline.
|
355
|
+
* This is necessary because of clearOnHide behavior that only clears when conditionally hidden - we need to track
|
356
|
+
* conditionallyHidden separately from "regular" visibility.
|
357
|
+
*/
|
358
|
+
this._parentConditionallyHidden = this.options.hasOwnProperty('parentConditionallyHidden') ? this.options.parentConditionallyHidden : false;
|
359
|
+
this._conditionallyHidden = this.checkConditionallyHidden(null, data) || this._parentConditionallyHidden;
|
353
360
|
/**
|
354
361
|
* Determines if this component is visible, or not.
|
355
362
|
*/
|
356
363
|
this._parentVisible = this.options.hasOwnProperty('parentVisible') ? this.options.parentVisible : true;
|
357
|
-
this._visible = this._parentVisible && this.
|
364
|
+
this._visible = this._parentVisible && (this.hasCondition() ? !this._conditionallyHidden : !this.component.hidden);
|
358
365
|
this._parentDisabled = false;
|
359
366
|
/**
|
360
367
|
* The reference attribute name for this component
|
@@ -423,7 +430,7 @@ class Component extends Element_1.default {
|
|
423
430
|
if (this.allowData && this.key) {
|
424
431
|
this.options.name += `[${this.key}]`;
|
425
432
|
// If component is visible or not set to clear on hide, set the default value.
|
426
|
-
if (this.
|
433
|
+
if (!(this.conditionallyHidden && this.component.clearOnHide)) {
|
427
434
|
if (!this.hasValue()) {
|
428
435
|
if (this.shouldAddDefaultValue) {
|
429
436
|
this.dataValue = this.defaultValue;
|
@@ -494,7 +501,8 @@ class Component extends Element_1.default {
|
|
494
501
|
init() {
|
495
502
|
var _a;
|
496
503
|
this.disabled = this.shouldDisabled;
|
497
|
-
this.
|
504
|
+
this._conditionallyHidden = this.checkConditionallyHidden();
|
505
|
+
this._visible = (this.hasCondition() ? !this.conditionallyHidden : !this.component.hidden);
|
498
506
|
if ((_a = this.component.addons) === null || _a === void 0 ? void 0 : _a.length) {
|
499
507
|
this.component.addons.forEach((addon) => this.createAddon(addon));
|
500
508
|
}
|
@@ -636,7 +644,6 @@ class Component extends Element_1.default {
|
|
636
644
|
return;
|
637
645
|
}
|
638
646
|
this._visible = value;
|
639
|
-
this.clearOnHide();
|
640
647
|
this.redraw();
|
641
648
|
}
|
642
649
|
}
|
@@ -657,6 +664,21 @@ class Component extends Element_1.default {
|
|
657
664
|
}
|
658
665
|
return this._visible && this._parentVisible;
|
659
666
|
}
|
667
|
+
get conditionallyHidden() {
|
668
|
+
return this._conditionallyHidden || this._parentConditionallyHidden;
|
669
|
+
}
|
670
|
+
/**
|
671
|
+
* Evaluates whether the component is conditionally hidden (as opposed to intentionally hidden, e.g. via the `hidden` component schema property).
|
672
|
+
* @param {object} data - The data object to evaluate the condition against.
|
673
|
+
* @param {object} row - The row object to evaluate the condition against.
|
674
|
+
* @returns {boolean} - Whether the component is conditionally hidden.
|
675
|
+
*/
|
676
|
+
checkConditionallyHidden(data = null, row = null) {
|
677
|
+
if (!this.hasCondition()) {
|
678
|
+
return false;
|
679
|
+
}
|
680
|
+
return !this.conditionallyVisible(data, row);
|
681
|
+
}
|
660
682
|
get currentForm() {
|
661
683
|
return this._currentForm;
|
662
684
|
}
|
@@ -1825,7 +1847,7 @@ class Component extends Element_1.default {
|
|
1825
1847
|
rebuild() {
|
1826
1848
|
this.destroy();
|
1827
1849
|
this.init();
|
1828
|
-
this.visible = this.
|
1850
|
+
this.visible = this.hasCondition() ? !this.conditionallyHidden : !this.component.hidden;
|
1829
1851
|
return this.redraw();
|
1830
1852
|
}
|
1831
1853
|
/**
|
@@ -1892,8 +1914,8 @@ class Component extends Element_1.default {
|
|
1892
1914
|
conditionallyVisible(data, row) {
|
1893
1915
|
data = data || this.rootValue;
|
1894
1916
|
row = row || this.data;
|
1895
|
-
if (this.builderMode || this.previewMode
|
1896
|
-
return
|
1917
|
+
if (this.builderMode || this.previewMode) {
|
1918
|
+
return true;
|
1897
1919
|
}
|
1898
1920
|
data = data || (this.root ? this.root.data : {});
|
1899
1921
|
return this.checkCondition(row, data);
|
@@ -1923,8 +1945,14 @@ class Component extends Element_1.default {
|
|
1923
1945
|
if (!this.builderMode & !this.previewMode && this.fieldLogic(data, row)) {
|
1924
1946
|
this.redraw();
|
1925
1947
|
}
|
1926
|
-
// Check advanced conditions
|
1927
|
-
const
|
1948
|
+
// Check advanced conditions (and cache the result)
|
1949
|
+
const isConditionallyHidden = this.checkConditionallyHidden(data, row) || this._parentConditionallyHidden;
|
1950
|
+
if (isConditionallyHidden !== this._conditionallyHidden) {
|
1951
|
+
this._conditionallyHidden = isConditionallyHidden;
|
1952
|
+
this.clearOnHide();
|
1953
|
+
}
|
1954
|
+
// Check visibility
|
1955
|
+
const visible = (this.hasCondition() ? !this.conditionallyHidden : !this.component.hidden);
|
1928
1956
|
if (this.visible !== visible) {
|
1929
1957
|
this.visible = visible;
|
1930
1958
|
}
|
@@ -2034,6 +2062,12 @@ class Component extends Element_1.default {
|
|
2034
2062
|
FormioUtils.setActionProperty(newComponent, action, result, row, data, this);
|
2035
2063
|
const property = action.property.value;
|
2036
2064
|
if (!lodash_1.default.isEqual(lodash_1.default.get(this.component, property), lodash_1.default.get(newComponent, property))) {
|
2065
|
+
// Advanced Logic can modify the component's hidden property; because we track conditionally hidden state
|
2066
|
+
// separately from the component's hidden property, and technically this Advanced Logic conditionally hides
|
2067
|
+
// a component, we need to set _conditionallyHidden to the new value
|
2068
|
+
if (property === 'hidden') {
|
2069
|
+
this._conditionallyHidden = newComponent.hidden;
|
2070
|
+
}
|
2037
2071
|
changed = true;
|
2038
2072
|
}
|
2039
2073
|
break;
|
@@ -2047,7 +2081,7 @@ class Component extends Element_1.default {
|
|
2047
2081
|
component: newComponent,
|
2048
2082
|
result,
|
2049
2083
|
});
|
2050
|
-
if (!lodash_1.default.isEqual(oldValue, newValue) && !(this.component.clearOnHide &&
|
2084
|
+
if (!lodash_1.default.isEqual(oldValue, newValue) && !(this.component.clearOnHide && this.conditionallyHidden)) {
|
2051
2085
|
this.setValue(newValue);
|
2052
2086
|
if (this.viewOnly) {
|
2053
2087
|
this.dataValue = newValue;
|
@@ -2080,7 +2114,7 @@ class Component extends Element_1.default {
|
|
2080
2114
|
component: newComponent,
|
2081
2115
|
result,
|
2082
2116
|
}, 'value');
|
2083
|
-
if (!lodash_1.default.isEqual(oldValue, newValue) && !(this.component.clearOnHide &&
|
2117
|
+
if (!lodash_1.default.isEqual(oldValue, newValue) && !(this.component.clearOnHide && this.conditionallyHidden)) {
|
2084
2118
|
this.setValue(newValue);
|
2085
2119
|
if (this.viewOnly) {
|
2086
2120
|
this.dataValue = newValue;
|
@@ -2191,7 +2225,7 @@ class Component extends Element_1.default {
|
|
2191
2225
|
this.component.clearOnHide !== false &&
|
2192
2226
|
!this.options.readOnly &&
|
2193
2227
|
!this.options.showHiddenFields) {
|
2194
|
-
if (
|
2228
|
+
if (this.conditionallyHidden) {
|
2195
2229
|
this.deleteValue();
|
2196
2230
|
}
|
2197
2231
|
else if (!this.hasValue() && this.shouldAddDefaultValue) {
|
@@ -2450,7 +2484,7 @@ class Component extends Element_1.default {
|
|
2450
2484
|
*/
|
2451
2485
|
get dataValue() {
|
2452
2486
|
if (!this.key ||
|
2453
|
-
(
|
2487
|
+
(this.conditionallyHidden && this.component.clearOnHide && !this.rootPristine)) {
|
2454
2488
|
return this.emptyValue;
|
2455
2489
|
}
|
2456
2490
|
if (!this.hasValue() && this.shouldAddDefaultValue) {
|
@@ -2469,7 +2503,7 @@ class Component extends Element_1.default {
|
|
2469
2503
|
set dataValue(value) {
|
2470
2504
|
if (!this.allowData ||
|
2471
2505
|
!this.key ||
|
2472
|
-
(
|
2506
|
+
(this.conditionallyHidden && this.component.clearOnHide && !this.rootPristine)) {
|
2473
2507
|
return;
|
2474
2508
|
}
|
2475
2509
|
if ((value !== null) && (value !== undefined)) {
|
@@ -2790,7 +2824,7 @@ class Component extends Element_1.default {
|
|
2790
2824
|
// If no calculated value or
|
2791
2825
|
// hidden and set to clearOnHide (Don't calculate a value for a hidden field set to clear when hidden)
|
2792
2826
|
const { clearOnHide } = this.component;
|
2793
|
-
const shouldBeCleared =
|
2827
|
+
const shouldBeCleared = this.conditionallyHidden && clearOnHide;
|
2794
2828
|
const allowOverride = lodash_1.default.get(this.component, 'allowCalculateOverride', false);
|
2795
2829
|
if (shouldBeCleared) {
|
2796
2830
|
// remove calculated value so that the value is recalculated once component becomes visible
|
@@ -3440,7 +3474,7 @@ class Component extends Element_1.default {
|
|
3440
3474
|
// If component definition changed, replace it.
|
3441
3475
|
if (!lodash_1.default.isEqual(this.component, newComponent)) {
|
3442
3476
|
this.component = newComponent;
|
3443
|
-
const visible = this.
|
3477
|
+
const visible = this.hasCondition() ? !this.conditionallyHidden : !this.component.hidden;
|
3444
3478
|
const disabled = this.shouldDisabled;
|
3445
3479
|
// Change states which won't be recalculated during redrawing
|
3446
3480
|
if (this.visible !== visible) {
|
@@ -133,10 +133,10 @@ exports.default = [
|
|
133
133
|
{
|
134
134
|
weight: 700,
|
135
135
|
type: 'checkbox',
|
136
|
-
label: '
|
136
|
+
label: 'Omit Value From Submission Data When Conditionally Hidden',
|
137
137
|
key: 'clearOnHide',
|
138
138
|
defaultValue: true,
|
139
|
-
tooltip: 'When a field is hidden,
|
139
|
+
tooltip: 'When a field is conditionally hidden, omit the value from the submission data.',
|
140
140
|
input: true
|
141
141
|
},
|
142
142
|
utils_1.default.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>'),
|
@@ -85,17 +85,26 @@ class NestedComponent extends Field_1.default {
|
|
85
85
|
const visibilityChanged = this._visible !== value;
|
86
86
|
this._visible = value;
|
87
87
|
const isVisible = this.visible;
|
88
|
+
const isConditionallyHidden = this.checkConditionallyHidden();
|
88
89
|
const forceShow = this.shouldForceShow();
|
89
90
|
const forceHide = this.shouldForceHide();
|
90
|
-
this.components.forEach(component => {
|
91
|
+
this.components.forEach((component) => {
|
91
92
|
// Set the parent visibility first since we may have nested components within nested components
|
92
93
|
// and they need to be able to determine their visibility based on the parent visibility.
|
93
94
|
component.parentVisible = isVisible;
|
94
|
-
|
95
|
-
|
95
|
+
component._parentConditionallyHidden = isConditionallyHidden;
|
96
|
+
let visible;
|
97
|
+
if (component.hasCondition()) {
|
98
|
+
component._conditionallyHidden = component.checkConditionallyHidden() || component._parentConditionallyHidden;
|
99
|
+
visible = !component.conditionallyHidden;
|
100
|
+
}
|
101
|
+
else {
|
102
|
+
visible = !component.component.hidden;
|
103
|
+
}
|
104
|
+
if (forceShow || visible) {
|
96
105
|
component.visible = true;
|
97
106
|
}
|
98
|
-
else if (forceHide || !isVisible || !
|
107
|
+
else if (forceHide || !isVisible || !visible) {
|
99
108
|
component.visible = false;
|
100
109
|
}
|
101
110
|
// If hiding a nested component, clear all errors below.
|
@@ -104,7 +113,6 @@ class NestedComponent extends Field_1.default {
|
|
104
113
|
}
|
105
114
|
});
|
106
115
|
if (visibilityChanged) {
|
107
|
-
this.clearOnHide();
|
108
116
|
this.redraw();
|
109
117
|
}
|
110
118
|
}
|
@@ -369,6 +377,7 @@ class NestedComponent extends Field_1.default {
|
|
369
377
|
data = data || this.data;
|
370
378
|
options.parent = this;
|
371
379
|
options.parentVisible = this.visible;
|
380
|
+
options.parentConditionallyHidden = this.conditionallyHidden;
|
372
381
|
options.root = (options === null || options === void 0 ? void 0 : options.root) || this.root || this;
|
373
382
|
options.localRoot = this.localRoot;
|
374
383
|
options.skipInit = true;
|
@@ -627,7 +636,7 @@ class NestedComponent extends Field_1.default {
|
|
627
636
|
clearOnHide(show) {
|
628
637
|
super.clearOnHide(show);
|
629
638
|
if (this.component.clearOnHide) {
|
630
|
-
if (this.allowData && !this.hasValue() && !
|
639
|
+
if (this.allowData && !this.hasValue() && !this.conditionallyHidden) {
|
631
640
|
this.dataValue = this.defaultValue;
|
632
641
|
}
|
633
642
|
if (this.hasValue()) {
|
@@ -656,7 +665,7 @@ class NestedComponent extends Field_1.default {
|
|
656
665
|
}
|
657
666
|
calculateValue(data, flags, row) {
|
658
667
|
// Do not iterate into children and calculateValues if this nested component is conditionally hidden.
|
659
|
-
if (
|
668
|
+
if (this.conditionallyHidden) {
|
660
669
|
return false;
|
661
670
|
}
|
662
671
|
return this.getComponents().reduce((changed, comp) => comp.calculateValue(data, flags, row) || changed, super.calculateValue(data, flags, row));
|
@@ -74,7 +74,7 @@ class DataMapComponent extends DataGrid_1.default {
|
|
74
74
|
}
|
75
75
|
get dataValue() {
|
76
76
|
if (!this.key ||
|
77
|
-
(
|
77
|
+
(this.conditionallyHidden && this.component.clearOnHide)) {
|
78
78
|
return this.emptyValue;
|
79
79
|
}
|
80
80
|
if (!this.hasValue() && this.shouldAddDefaultValue) {
|
@@ -43,7 +43,7 @@ export default class EditGridComponent extends NestedArrayComponent {
|
|
43
43
|
get defaultValue(): any[];
|
44
44
|
hasRemoveButtons(): boolean;
|
45
45
|
editRows: any;
|
46
|
-
checkRowVariableTypeComponents(editRow: any, rowIndex: any):
|
46
|
+
checkRowVariableTypeComponents(editRow: any, rowIndex: any): boolean;
|
47
47
|
setVariableTypeComponents(): void;
|
48
48
|
variableTypeComponentsIndexes: any[] | undefined;
|
49
49
|
isOpen(editRow: any): boolean;
|
@@ -294,12 +294,15 @@ class EditGridComponent extends NestedArrayComponent_1.default {
|
|
294
294
|
}
|
295
295
|
checkRowVariableTypeComponents(editRow, rowIndex) {
|
296
296
|
const rowComponents = editRow.components;
|
297
|
+
let typeChanged = false;
|
297
298
|
if (lodash_1.default.some(this.variableTypeComponentsIndexes, (compIndex) => {
|
298
299
|
const variableTypeComp = rowComponents[compIndex];
|
299
300
|
return variableTypeComp.type !== variableTypeComp.component.type;
|
300
301
|
})) {
|
301
302
|
editRow.components = this.createRowComponents(editRow.data, rowIndex, true);
|
303
|
+
typeChanged = true;
|
302
304
|
}
|
305
|
+
return typeChanged;
|
303
306
|
}
|
304
307
|
setVariableTypeComponents() {
|
305
308
|
//set components which type is changing within a row (e.g.,by mergeComponentSchema action)
|
@@ -952,8 +955,10 @@ class EditGridComponent extends NestedArrayComponent_1.default {
|
|
952
955
|
this.validateRow(editRow, false, false);
|
953
956
|
}
|
954
957
|
if (this.variableTypeComponentsIndexes.length) {
|
955
|
-
this.checkRowVariableTypeComponents(editRow, rowIndex);
|
956
|
-
|
958
|
+
const typeChanged = this.checkRowVariableTypeComponents(editRow, rowIndex);
|
959
|
+
if (typeChanged) {
|
960
|
+
this.redraw();
|
961
|
+
}
|
957
962
|
}
|
958
963
|
};
|
959
964
|
const comp = this.createComponent(lodash_1.default.assign({}, column, { row: options.row }), options, row, null, recreatePartially && currentRowComponents ? currentRowComponents[colIndex] : null);
|
@@ -1154,7 +1159,7 @@ class EditGridComponent extends NestedArrayComponent_1.default {
|
|
1154
1159
|
}
|
1155
1160
|
}
|
1156
1161
|
const changed = this.hasChanged(value, this.dataValue);
|
1157
|
-
if (this.parent
|
1162
|
+
if (this.parent) {
|
1158
1163
|
this.parent.checkComponentConditions();
|
1159
1164
|
}
|
1160
1165
|
this.dataValue = value;
|
@@ -1187,10 +1192,7 @@ class EditGridComponent extends NestedArrayComponent_1.default {
|
|
1187
1192
|
this.editRows = this.editRows.slice(0, dataLength);
|
1188
1193
|
this.openWhenEmpty();
|
1189
1194
|
this.updateOnChange(flags, changed);
|
1190
|
-
|
1191
|
-
if (!this.options.server) {
|
1192
|
-
this.checkData();
|
1193
|
-
}
|
1195
|
+
this.checkData();
|
1194
1196
|
this.changeState(changed, flags);
|
1195
1197
|
return changed;
|
1196
1198
|
}
|
@@ -425,10 +425,11 @@ class FormComponent extends Component_1.default {
|
|
425
425
|
return this.subFormReady;
|
426
426
|
}
|
427
427
|
hideSubmitButton(component) {
|
428
|
-
const isSubmitButton =
|
429
|
-
((component.action === 'submit') || !component.action);
|
428
|
+
const isSubmitButton = component.type === 'button' && (component.action === 'submit' || !component.action);
|
430
429
|
if (isSubmitButton) {
|
431
430
|
component.hidden = true;
|
431
|
+
// clearOnHide no longer clears from the JSON `hidden` flag, so we make the button conditionally hidden to clear its data
|
432
|
+
component.customConditional = 'show = false';
|
432
433
|
}
|
433
434
|
}
|
434
435
|
/**
|
@@ -438,7 +439,7 @@ class FormComponent extends Component_1.default {
|
|
438
439
|
*/
|
439
440
|
loadSubForm(fromAttach) {
|
440
441
|
var _a, _b, _c, _d, _e;
|
441
|
-
if (this.builderMode || this.
|
442
|
+
if (this.builderMode || this.conditionallyHidden || (this.isSubFormLazyLoad() && !fromAttach)) {
|
442
443
|
return Promise.resolve();
|
443
444
|
}
|
444
445
|
if (this.hasLoadedForm && !this.isRevisionChanged &&
|
@@ -510,7 +511,7 @@ class FormComponent extends Component_1.default {
|
|
510
511
|
* @returns {*|boolean} - TRUE if the subform should be submitted, FALSE if it should not.
|
511
512
|
*/
|
512
513
|
get shouldSubmit() {
|
513
|
-
return this.subFormReady && (!this.component.hasOwnProperty('reference') || this.component.reference) && !this.
|
514
|
+
return this.subFormReady && (!this.component.hasOwnProperty('reference') || this.component.reference) && !this.conditionallyHidden;
|
514
515
|
}
|
515
516
|
/**
|
516
517
|
* Returns the data for the subform.
|
@@ -56,9 +56,21 @@ class HTMLComponent extends Component_1.default {
|
|
56
56
|
}
|
57
57
|
checkRefreshOn(changed) {
|
58
58
|
super.checkRefreshOn(changed);
|
59
|
-
|
60
|
-
|
61
|
-
this.
|
59
|
+
let visible;
|
60
|
+
if (this.hasCondition()) {
|
61
|
+
this._conditionallyHidden = this.checkConditionallyHidden();
|
62
|
+
visible = !this.conditionallyHidden;
|
63
|
+
}
|
64
|
+
else {
|
65
|
+
visible = !this.component.hidden;
|
66
|
+
}
|
67
|
+
const shouldSetContent = !this.builderMode
|
68
|
+
&& this.component.refreshOnChange
|
69
|
+
&& this.element
|
70
|
+
&& !lodash_1.default.isUndefined(changed)
|
71
|
+
&& ((lodash_1.default.isBoolean(changed) && changed) || !lodash_1.default.isEmpty(changed))
|
72
|
+
&& visible;
|
73
|
+
if (shouldSetContent) {
|
62
74
|
this.setContent(this.element, this.renderContent());
|
63
75
|
}
|
64
76
|
}
|
package/lib/cjs/formio.form.js
CHANGED
@@ -73,6 +73,7 @@ function registerModule(mod, defaultFn = null, options = {}) {
|
|
73
73
|
case 'templates':
|
74
74
|
for (const framework of Object.keys(mod.templates)) {
|
75
75
|
Formio_1.Formio.Templates.extendTemplate(framework, mod.templates[framework]);
|
76
|
+
Formio_1.Formio.Templates.defaultTemplates = lodash_1.default.defaults(mod.templates[framework], Formio_1.Formio.Templates.defaultTemplates);
|
76
77
|
}
|
77
78
|
if (mod.templates[current]) {
|
78
79
|
Formio_1.Formio.Templates.current = mod.templates[current];
|
@@ -119,6 +119,13 @@ declare class Component extends Element {
|
|
119
119
|
*/
|
120
120
|
paths: import('@formio/core').ComponentPaths;
|
121
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;
|
122
129
|
/**
|
123
130
|
* Determines if this component is visible, or not.
|
124
131
|
*/
|
@@ -224,6 +231,14 @@ declare class Component extends Element {
|
|
224
231
|
* @returns {boolean} - Whether the component is visible or not.
|
225
232
|
*/
|
226
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;
|
227
242
|
set currentForm(instance: any);
|
228
243
|
get currentForm(): any;
|
229
244
|
_currentForm: any;
|
@@ -315,11 +315,18 @@ export default class Component extends Element {
|
|
315
315
|
this._path = '';
|
316
316
|
// Needs for Nextgen Rules Engine
|
317
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;
|
318
325
|
/**
|
319
326
|
* Determines if this component is visible, or not.
|
320
327
|
*/
|
321
328
|
this._parentVisible = this.options.hasOwnProperty('parentVisible') ? this.options.parentVisible : true;
|
322
|
-
this._visible = this._parentVisible && this.
|
329
|
+
this._visible = this._parentVisible && (this.hasCondition() ? !this._conditionallyHidden : !this.component.hidden);
|
323
330
|
this._parentDisabled = false;
|
324
331
|
/**
|
325
332
|
* The reference attribute name for this component
|
@@ -388,7 +395,7 @@ export default class Component extends Element {
|
|
388
395
|
if (this.allowData && this.key) {
|
389
396
|
this.options.name += `[${this.key}]`;
|
390
397
|
// If component is visible or not set to clear on hide, set the default value.
|
391
|
-
if (this.
|
398
|
+
if (!(this.conditionallyHidden && this.component.clearOnHide)) {
|
392
399
|
if (!this.hasValue()) {
|
393
400
|
if (this.shouldAddDefaultValue) {
|
394
401
|
this.dataValue = this.defaultValue;
|
@@ -457,7 +464,8 @@ export default class Component extends Element {
|
|
457
464
|
}
|
458
465
|
init() {
|
459
466
|
this.disabled = this.shouldDisabled;
|
460
|
-
this.
|
467
|
+
this._conditionallyHidden = this.checkConditionallyHidden();
|
468
|
+
this._visible = (this.hasCondition() ? !this.conditionallyHidden : !this.component.hidden);
|
461
469
|
if (this.component.addons?.length) {
|
462
470
|
this.component.addons.forEach((addon) => this.createAddon(addon));
|
463
471
|
}
|
@@ -600,7 +608,6 @@ export default class Component extends Element {
|
|
600
608
|
return;
|
601
609
|
}
|
602
610
|
this._visible = value;
|
603
|
-
this.clearOnHide();
|
604
611
|
this.redraw();
|
605
612
|
}
|
606
613
|
}
|
@@ -621,6 +628,21 @@ export default class Component extends Element {
|
|
621
628
|
}
|
622
629
|
return this._visible && this._parentVisible;
|
623
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
|
+
}
|
624
646
|
get currentForm() {
|
625
647
|
return this._currentForm;
|
626
648
|
}
|
@@ -1791,7 +1813,7 @@ export default class Component extends Element {
|
|
1791
1813
|
rebuild() {
|
1792
1814
|
this.destroy();
|
1793
1815
|
this.init();
|
1794
|
-
this.visible = this.
|
1816
|
+
this.visible = this.hasCondition() ? !this.conditionallyHidden : !this.component.hidden;
|
1795
1817
|
return this.redraw();
|
1796
1818
|
}
|
1797
1819
|
/**
|
@@ -1858,8 +1880,8 @@ export default class Component extends Element {
|
|
1858
1880
|
conditionallyVisible(data, row) {
|
1859
1881
|
data = data || this.rootValue;
|
1860
1882
|
row = row || this.data;
|
1861
|
-
if (this.builderMode || this.previewMode
|
1862
|
-
return
|
1883
|
+
if (this.builderMode || this.previewMode) {
|
1884
|
+
return true;
|
1863
1885
|
}
|
1864
1886
|
data = data || (this.root ? this.root.data : {});
|
1865
1887
|
return this.checkCondition(row, data);
|
@@ -1889,8 +1911,14 @@ export default class Component extends Element {
|
|
1889
1911
|
if (!this.builderMode & !this.previewMode && this.fieldLogic(data, row)) {
|
1890
1912
|
this.redraw();
|
1891
1913
|
}
|
1892
|
-
// Check advanced conditions
|
1893
|
-
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);
|
1894
1922
|
if (this.visible !== visible) {
|
1895
1923
|
this.visible = visible;
|
1896
1924
|
}
|
@@ -2000,6 +2028,12 @@ export default class Component extends Element {
|
|
2000
2028
|
FormioUtils.setActionProperty(newComponent, action, result, row, data, this);
|
2001
2029
|
const property = action.property.value;
|
2002
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
|
+
}
|
2003
2037
|
changed = true;
|
2004
2038
|
}
|
2005
2039
|
break;
|
@@ -2013,7 +2047,7 @@ export default class Component extends Element {
|
|
2013
2047
|
component: newComponent,
|
2014
2048
|
result,
|
2015
2049
|
});
|
2016
|
-
if (!_.isEqual(oldValue, newValue) && !(this.component.clearOnHide &&
|
2050
|
+
if (!_.isEqual(oldValue, newValue) && !(this.component.clearOnHide && this.conditionallyHidden)) {
|
2017
2051
|
this.setValue(newValue);
|
2018
2052
|
if (this.viewOnly) {
|
2019
2053
|
this.dataValue = newValue;
|
@@ -2046,7 +2080,7 @@ export default class Component extends Element {
|
|
2046
2080
|
component: newComponent,
|
2047
2081
|
result,
|
2048
2082
|
}, 'value');
|
2049
|
-
if (!_.isEqual(oldValue, newValue) && !(this.component.clearOnHide &&
|
2083
|
+
if (!_.isEqual(oldValue, newValue) && !(this.component.clearOnHide && this.conditionallyHidden)) {
|
2050
2084
|
this.setValue(newValue);
|
2051
2085
|
if (this.viewOnly) {
|
2052
2086
|
this.dataValue = newValue;
|
@@ -2157,7 +2191,7 @@ export default class Component extends Element {
|
|
2157
2191
|
this.component.clearOnHide !== false &&
|
2158
2192
|
!this.options.readOnly &&
|
2159
2193
|
!this.options.showHiddenFields) {
|
2160
|
-
if (
|
2194
|
+
if (this.conditionallyHidden) {
|
2161
2195
|
this.deleteValue();
|
2162
2196
|
}
|
2163
2197
|
else if (!this.hasValue() && this.shouldAddDefaultValue) {
|
@@ -2419,7 +2453,7 @@ export default class Component extends Element {
|
|
2419
2453
|
*/
|
2420
2454
|
get dataValue() {
|
2421
2455
|
if (!this.key ||
|
2422
|
-
(
|
2456
|
+
(this.conditionallyHidden && this.component.clearOnHide && !this.rootPristine)) {
|
2423
2457
|
return this.emptyValue;
|
2424
2458
|
}
|
2425
2459
|
if (!this.hasValue() && this.shouldAddDefaultValue) {
|
@@ -2438,7 +2472,7 @@ export default class Component extends Element {
|
|
2438
2472
|
set dataValue(value) {
|
2439
2473
|
if (!this.allowData ||
|
2440
2474
|
!this.key ||
|
2441
|
-
(
|
2475
|
+
(this.conditionallyHidden && this.component.clearOnHide && !this.rootPristine)) {
|
2442
2476
|
return;
|
2443
2477
|
}
|
2444
2478
|
if ((value !== null) && (value !== undefined)) {
|
@@ -2758,7 +2792,7 @@ export default class Component extends Element {
|
|
2758
2792
|
// If no calculated value or
|
2759
2793
|
// hidden and set to clearOnHide (Don't calculate a value for a hidden field set to clear when hidden)
|
2760
2794
|
const { clearOnHide } = this.component;
|
2761
|
-
const shouldBeCleared =
|
2795
|
+
const shouldBeCleared = this.conditionallyHidden && clearOnHide;
|
2762
2796
|
const allowOverride = _.get(this.component, 'allowCalculateOverride', false);
|
2763
2797
|
if (shouldBeCleared) {
|
2764
2798
|
// remove calculated value so that the value is recalculated once component becomes visible
|
@@ -3403,7 +3437,7 @@ export default class Component extends Element {
|
|
3403
3437
|
// If component definition changed, replace it.
|
3404
3438
|
if (!_.isEqual(this.component, newComponent)) {
|
3405
3439
|
this.component = newComponent;
|
3406
|
-
const visible = this.
|
3440
|
+
const visible = this.hasCondition() ? !this.conditionallyHidden : !this.component.hidden;
|
3407
3441
|
const disabled = this.shouldDisabled;
|
3408
3442
|
// Change states which won't be recalculated during redrawing
|
3409
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>'),
|