@formio/js 5.0.0-dev.5898.ffba52a → 5.0.0-dev.5902.bf899bf
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 +8 -8
- package/dist/formio.form.min.js +1 -1
- package/dist/formio.full.js +8 -8
- 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.js +2 -5
- package/lib/cjs/components/form/Form.js +4 -4
- package/lib/cjs/components/html/HTML.js +15 -3
- package/lib/cjs/components/radio/Radio.js +2 -3
- 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.js +2 -5
- package/lib/mjs/components/form/Form.js +4 -4
- package/lib/mjs/components/html/HTML.js +15 -3
- package/lib/mjs/components/radio/Radio.js +2 -3
- package/package.json +1 -1
|
@@ -115,6 +115,13 @@ declare class Component extends Element {
|
|
|
115
115
|
*/
|
|
116
116
|
parent: Component;
|
|
117
117
|
_path: string;
|
|
118
|
+
/**
|
|
119
|
+
* Determines if this component is conditionally hidden. Should generally not be set outside of conditional logic pipeline.
|
|
120
|
+
* This is necessary because of clearOnHide behavior that only clears when conditionally hidden - we need to track
|
|
121
|
+
* conditionallyHidden separately from "regular" visibility.
|
|
122
|
+
*/
|
|
123
|
+
_parentConditionallyHidden: any;
|
|
124
|
+
_conditionallyHidden: any;
|
|
118
125
|
/**
|
|
119
126
|
* Determines if this component is visible, or not.
|
|
120
127
|
*/
|
|
@@ -207,6 +214,14 @@ declare class Component extends Element {
|
|
|
207
214
|
* @returns {boolean} - Whether the component is visible or not.
|
|
208
215
|
*/
|
|
209
216
|
get visible(): boolean;
|
|
217
|
+
get conditionallyHidden(): any;
|
|
218
|
+
/**
|
|
219
|
+
* Evaluates whether the component is conditionally hidden (as opposed to intentionally hidden, e.g. via the `hidden` component schema property).
|
|
220
|
+
* @param {object} data - The data object to evaluate the condition against.
|
|
221
|
+
* @param {object} row - The row object to evaluate the condition against.
|
|
222
|
+
* @returns {boolean} - Whether the component is conditionally hidden.
|
|
223
|
+
*/
|
|
224
|
+
checkConditionallyHidden(data?: object, row?: object): boolean;
|
|
210
225
|
set currentForm(instance: any);
|
|
211
226
|
get currentForm(): any;
|
|
212
227
|
_currentForm: any;
|
|
@@ -345,11 +345,18 @@ class Component extends Element_1.default {
|
|
|
345
345
|
this._path = '';
|
|
346
346
|
// Needs for Nextgen Rules Engine
|
|
347
347
|
this.resetCaches();
|
|
348
|
+
/**
|
|
349
|
+
* Determines if this component is conditionally hidden. Should generally not be set outside of conditional logic pipeline.
|
|
350
|
+
* This is necessary because of clearOnHide behavior that only clears when conditionally hidden - we need to track
|
|
351
|
+
* conditionallyHidden separately from "regular" visibility.
|
|
352
|
+
*/
|
|
353
|
+
this._parentConditionallyHidden = this.options.hasOwnProperty('parentConditionallyHidden') ? this.options.parentConditionallyHidden : false;
|
|
354
|
+
this._conditionallyHidden = this.checkConditionallyHidden(null, data) || this._parentConditionallyHidden;
|
|
348
355
|
/**
|
|
349
356
|
* Determines if this component is visible, or not.
|
|
350
357
|
*/
|
|
351
358
|
this._parentVisible = this.options.hasOwnProperty('parentVisible') ? this.options.parentVisible : true;
|
|
352
|
-
this._visible = this._parentVisible && this.
|
|
359
|
+
this._visible = this._parentVisible && (this.hasCondition() ? !this._conditionallyHidden : !this.component.hidden);
|
|
353
360
|
this._parentDisabled = false;
|
|
354
361
|
/**
|
|
355
362
|
* The reference attribute name for this component
|
|
@@ -418,7 +425,7 @@ class Component extends Element_1.default {
|
|
|
418
425
|
if (this.allowData && this.key) {
|
|
419
426
|
this.options.name += `[${this.key}]`;
|
|
420
427
|
// If component is visible or not set to clear on hide, set the default value.
|
|
421
|
-
if (this.
|
|
428
|
+
if (!(this.conditionallyHidden && this.component.clearOnHide)) {
|
|
422
429
|
if (!this.hasValue()) {
|
|
423
430
|
if (this.shouldAddDefaultValue) {
|
|
424
431
|
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
|
}
|
|
@@ -613,7 +621,6 @@ class Component extends Element_1.default {
|
|
|
613
621
|
return;
|
|
614
622
|
}
|
|
615
623
|
this._visible = value;
|
|
616
|
-
this.clearOnHide();
|
|
617
624
|
this.redraw();
|
|
618
625
|
}
|
|
619
626
|
}
|
|
@@ -634,6 +641,21 @@ class Component extends Element_1.default {
|
|
|
634
641
|
}
|
|
635
642
|
return this._visible && this._parentVisible;
|
|
636
643
|
}
|
|
644
|
+
get conditionallyHidden() {
|
|
645
|
+
return this._conditionallyHidden || this._parentConditionallyHidden;
|
|
646
|
+
}
|
|
647
|
+
/**
|
|
648
|
+
* Evaluates whether the component is conditionally hidden (as opposed to intentionally hidden, e.g. via the `hidden` component schema property).
|
|
649
|
+
* @param {object} data - The data object to evaluate the condition against.
|
|
650
|
+
* @param {object} row - The row object to evaluate the condition against.
|
|
651
|
+
* @returns {boolean} - Whether the component is conditionally hidden.
|
|
652
|
+
*/
|
|
653
|
+
checkConditionallyHidden(data = null, row = null) {
|
|
654
|
+
if (!this.hasCondition()) {
|
|
655
|
+
return false;
|
|
656
|
+
}
|
|
657
|
+
return !this.conditionallyVisible(data, row);
|
|
658
|
+
}
|
|
637
659
|
get currentForm() {
|
|
638
660
|
return this._currentForm;
|
|
639
661
|
}
|
|
@@ -1801,7 +1823,7 @@ class Component extends Element_1.default {
|
|
|
1801
1823
|
rebuild() {
|
|
1802
1824
|
this.destroy();
|
|
1803
1825
|
this.init();
|
|
1804
|
-
this.visible = this.
|
|
1826
|
+
this.visible = this.hasCondition() ? !this.conditionallyHidden : !this.component.hidden;
|
|
1805
1827
|
return this.redraw();
|
|
1806
1828
|
}
|
|
1807
1829
|
/**
|
|
@@ -1868,8 +1890,8 @@ class Component extends Element_1.default {
|
|
|
1868
1890
|
conditionallyVisible(data, row) {
|
|
1869
1891
|
data = data || this.rootValue;
|
|
1870
1892
|
row = row || this.data;
|
|
1871
|
-
if (this.builderMode || this.previewMode
|
|
1872
|
-
return
|
|
1893
|
+
if (this.builderMode || this.previewMode) {
|
|
1894
|
+
return true;
|
|
1873
1895
|
}
|
|
1874
1896
|
data = data || (this.root ? this.root.data : {});
|
|
1875
1897
|
return this.checkCondition(row, data);
|
|
@@ -1899,8 +1921,14 @@ class Component extends Element_1.default {
|
|
|
1899
1921
|
if (!this.builderMode & !this.previewMode && this.fieldLogic(data, row)) {
|
|
1900
1922
|
this.redraw();
|
|
1901
1923
|
}
|
|
1902
|
-
// Check advanced conditions
|
|
1903
|
-
const
|
|
1924
|
+
// Check advanced conditions (and cache the result)
|
|
1925
|
+
const isConditionallyHidden = this.checkConditionallyHidden(data, row) || this._parentConditionallyHidden;
|
|
1926
|
+
if (isConditionallyHidden !== this._conditionallyHidden) {
|
|
1927
|
+
this._conditionallyHidden = isConditionallyHidden;
|
|
1928
|
+
this.clearOnHide();
|
|
1929
|
+
}
|
|
1930
|
+
// Check visibility
|
|
1931
|
+
const visible = (this.hasCondition() ? !this.conditionallyHidden : !this.component.hidden);
|
|
1904
1932
|
if (this.visible !== visible) {
|
|
1905
1933
|
this.visible = visible;
|
|
1906
1934
|
}
|
|
@@ -2010,6 +2038,12 @@ class Component extends Element_1.default {
|
|
|
2010
2038
|
FormioUtils.setActionProperty(newComponent, action, result, row, data, this);
|
|
2011
2039
|
const property = action.property.value;
|
|
2012
2040
|
if (!lodash_1.default.isEqual(lodash_1.default.get(this.component, property), lodash_1.default.get(newComponent, property))) {
|
|
2041
|
+
// Advanced Logic can modify the component's hidden property; because we track conditionally hidden state
|
|
2042
|
+
// separately from the component's hidden property, and technically this Advanced Logic conditionally hides
|
|
2043
|
+
// a component, we need to set _conditionallyHidden to the new value
|
|
2044
|
+
if (property === 'hidden') {
|
|
2045
|
+
this._conditionallyHidden = newComponent.hidden;
|
|
2046
|
+
}
|
|
2013
2047
|
changed = true;
|
|
2014
2048
|
}
|
|
2015
2049
|
break;
|
|
@@ -2023,7 +2057,7 @@ class Component extends Element_1.default {
|
|
|
2023
2057
|
component: newComponent,
|
|
2024
2058
|
result,
|
|
2025
2059
|
});
|
|
2026
|
-
if (!lodash_1.default.isEqual(oldValue, newValue) && !(this.component.clearOnHide &&
|
|
2060
|
+
if (!lodash_1.default.isEqual(oldValue, newValue) && !(this.component.clearOnHide && this.conditionallyHidden)) {
|
|
2027
2061
|
this.setValue(newValue);
|
|
2028
2062
|
if (this.viewOnly) {
|
|
2029
2063
|
this.dataValue = newValue;
|
|
@@ -2056,7 +2090,7 @@ class Component extends Element_1.default {
|
|
|
2056
2090
|
component: newComponent,
|
|
2057
2091
|
result,
|
|
2058
2092
|
}, 'value');
|
|
2059
|
-
if (!lodash_1.default.isEqual(oldValue, newValue) && !(this.component.clearOnHide &&
|
|
2093
|
+
if (!lodash_1.default.isEqual(oldValue, newValue) && !(this.component.clearOnHide && this.conditionallyHidden)) {
|
|
2060
2094
|
this.setValue(newValue);
|
|
2061
2095
|
if (this.viewOnly) {
|
|
2062
2096
|
this.dataValue = newValue;
|
|
@@ -2167,7 +2201,7 @@ class Component extends Element_1.default {
|
|
|
2167
2201
|
this.component.clearOnHide !== false &&
|
|
2168
2202
|
!this.options.readOnly &&
|
|
2169
2203
|
!this.options.showHiddenFields) {
|
|
2170
|
-
if (
|
|
2204
|
+
if (this.conditionallyHidden) {
|
|
2171
2205
|
this.deleteValue();
|
|
2172
2206
|
}
|
|
2173
2207
|
else if (!this.hasValue() && this.shouldAddDefaultValue) {
|
|
@@ -2426,7 +2460,7 @@ class Component extends Element_1.default {
|
|
|
2426
2460
|
*/
|
|
2427
2461
|
get dataValue() {
|
|
2428
2462
|
if (!this.key ||
|
|
2429
|
-
(
|
|
2463
|
+
(this.conditionallyHidden && this.component.clearOnHide && !this.rootPristine)) {
|
|
2430
2464
|
return this.emptyValue;
|
|
2431
2465
|
}
|
|
2432
2466
|
if (!this.hasValue() && this.shouldAddDefaultValue) {
|
|
@@ -2445,7 +2479,7 @@ class Component extends Element_1.default {
|
|
|
2445
2479
|
set dataValue(value) {
|
|
2446
2480
|
if (!this.allowData ||
|
|
2447
2481
|
!this.key ||
|
|
2448
|
-
(
|
|
2482
|
+
(this.conditionallyHidden && this.component.clearOnHide && !this.rootPristine)) {
|
|
2449
2483
|
return;
|
|
2450
2484
|
}
|
|
2451
2485
|
if ((value !== null) && (value !== undefined)) {
|
|
@@ -2766,7 +2800,7 @@ class Component extends Element_1.default {
|
|
|
2766
2800
|
// If no calculated value or
|
|
2767
2801
|
// hidden and set to clearOnHide (Don't calculate a value for a hidden field set to clear when hidden)
|
|
2768
2802
|
const { clearOnHide } = this.component;
|
|
2769
|
-
const shouldBeCleared =
|
|
2803
|
+
const shouldBeCleared = this.conditionallyHidden && clearOnHide;
|
|
2770
2804
|
const allowOverride = lodash_1.default.get(this.component, 'allowCalculateOverride', false);
|
|
2771
2805
|
if (shouldBeCleared) {
|
|
2772
2806
|
// remove calculated value so that the value is recalculated once component becomes visible
|
|
@@ -3405,7 +3439,7 @@ class Component extends Element_1.default {
|
|
|
3405
3439
|
// If component definition changed, replace it.
|
|
3406
3440
|
if (!lodash_1.default.isEqual(this.component, newComponent)) {
|
|
3407
3441
|
this.component = newComponent;
|
|
3408
|
-
const visible = this.
|
|
3442
|
+
const visible = this.hasCondition() ? !this.conditionallyHidden : !this.component.hidden;
|
|
3409
3443
|
const disabled = this.shouldDisabled;
|
|
3410
3444
|
// Change states which won't be recalculated during redrawing
|
|
3411
3445
|
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>'),
|
|
@@ -84,17 +84,26 @@ class NestedComponent extends Field_1.default {
|
|
|
84
84
|
const visibilityChanged = this._visible !== value;
|
|
85
85
|
this._visible = value;
|
|
86
86
|
const isVisible = this.visible;
|
|
87
|
+
const isConditionallyHidden = this.checkConditionallyHidden();
|
|
87
88
|
const forceShow = this.shouldForceShow();
|
|
88
89
|
const forceHide = this.shouldForceHide();
|
|
89
|
-
this.components.forEach(component => {
|
|
90
|
+
this.components.forEach((component) => {
|
|
90
91
|
// Set the parent visibility first since we may have nested components within nested components
|
|
91
92
|
// and they need to be able to determine their visibility based on the parent visibility.
|
|
92
93
|
component.parentVisible = isVisible;
|
|
93
|
-
|
|
94
|
-
|
|
94
|
+
component._parentConditionallyHidden = isConditionallyHidden;
|
|
95
|
+
let visible;
|
|
96
|
+
if (component.hasCondition()) {
|
|
97
|
+
component._conditionallyHidden = component.checkConditionallyHidden() || component._parentConditionallyHidden;
|
|
98
|
+
visible = !component.conditionallyHidden;
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
visible = !component.component.hidden;
|
|
102
|
+
}
|
|
103
|
+
if (forceShow || visible) {
|
|
95
104
|
component.visible = true;
|
|
96
105
|
}
|
|
97
|
-
else if (forceHide || !isVisible || !
|
|
106
|
+
else if (forceHide || !isVisible || !visible) {
|
|
98
107
|
component.visible = false;
|
|
99
108
|
}
|
|
100
109
|
// If hiding a nested component, clear all errors below.
|
|
@@ -103,7 +112,6 @@ class NestedComponent extends Field_1.default {
|
|
|
103
112
|
}
|
|
104
113
|
});
|
|
105
114
|
if (visibilityChanged) {
|
|
106
|
-
this.clearOnHide();
|
|
107
115
|
this.redraw();
|
|
108
116
|
}
|
|
109
117
|
}
|
|
@@ -384,6 +392,7 @@ class NestedComponent extends Field_1.default {
|
|
|
384
392
|
data = data || this.data;
|
|
385
393
|
options.parent = this;
|
|
386
394
|
options.parentVisible = this.visible;
|
|
395
|
+
options.parentConditionallyHidden = this.conditionallyHidden;
|
|
387
396
|
options.root = (options === null || options === void 0 ? void 0 : options.root) || this.root || this;
|
|
388
397
|
options.localRoot = this.localRoot;
|
|
389
398
|
options.skipInit = true;
|
|
@@ -642,7 +651,7 @@ class NestedComponent extends Field_1.default {
|
|
|
642
651
|
clearOnHide(show) {
|
|
643
652
|
super.clearOnHide(show);
|
|
644
653
|
if (this.component.clearOnHide) {
|
|
645
|
-
if (this.allowData && !this.hasValue() && !
|
|
654
|
+
if (this.allowData && !this.hasValue() && !this.conditionallyHidden) {
|
|
646
655
|
this.dataValue = this.defaultValue;
|
|
647
656
|
}
|
|
648
657
|
if (this.hasValue()) {
|
|
@@ -671,7 +680,7 @@ class NestedComponent extends Field_1.default {
|
|
|
671
680
|
}
|
|
672
681
|
calculateValue(data, flags, row) {
|
|
673
682
|
// Do not iterate into children and calculateValues if this nested component is conditionally hidden.
|
|
674
|
-
if (
|
|
683
|
+
if (this.conditionallyHidden) {
|
|
675
684
|
return false;
|
|
676
685
|
}
|
|
677
686
|
return this.getComponents().reduce((changed, comp) => comp.calculateValue(data, flags, row) || changed, super.calculateValue(data, flags, row));
|
|
@@ -75,7 +75,7 @@ class DataMapComponent extends DataGrid_1.default {
|
|
|
75
75
|
}
|
|
76
76
|
get dataValue() {
|
|
77
77
|
if (!this.key ||
|
|
78
|
-
(
|
|
78
|
+
(this.conditionallyHidden && this.component.clearOnHide)) {
|
|
79
79
|
return this.emptyValue;
|
|
80
80
|
}
|
|
81
81
|
if (!this.hasValue() && this.shouldAddDefaultValue) {
|
|
@@ -1151,7 +1151,7 @@ class EditGridComponent extends NestedArrayComponent_1.default {
|
|
|
1151
1151
|
}
|
|
1152
1152
|
}
|
|
1153
1153
|
const changed = this.hasChanged(value, this.dataValue);
|
|
1154
|
-
if (this.parent
|
|
1154
|
+
if (this.parent) {
|
|
1155
1155
|
this.parent.checkComponentConditions();
|
|
1156
1156
|
}
|
|
1157
1157
|
this.dataValue = value;
|
|
@@ -1184,10 +1184,7 @@ class EditGridComponent extends NestedArrayComponent_1.default {
|
|
|
1184
1184
|
this.editRows = this.editRows.slice(0, dataLength);
|
|
1185
1185
|
this.openWhenEmpty();
|
|
1186
1186
|
this.updateOnChange(flags, changed);
|
|
1187
|
-
|
|
1188
|
-
if (!this.options.server) {
|
|
1189
|
-
this.checkData();
|
|
1190
|
-
}
|
|
1187
|
+
this.checkData();
|
|
1191
1188
|
this.changeState(changed, flags);
|
|
1192
1189
|
return changed;
|
|
1193
1190
|
}
|
|
@@ -421,10 +421,10 @@ class FormComponent extends Component_1.default {
|
|
|
421
421
|
return this.subFormReady;
|
|
422
422
|
}
|
|
423
423
|
hideSubmitButton(component) {
|
|
424
|
-
const isSubmitButton =
|
|
425
|
-
((component.action === 'submit') || !component.action);
|
|
424
|
+
const isSubmitButton = component.type === 'button' && (component.action === 'submit' || !component.action);
|
|
426
425
|
if (isSubmitButton) {
|
|
427
426
|
component.hidden = true;
|
|
427
|
+
component.customConditional = 'show = false';
|
|
428
428
|
}
|
|
429
429
|
}
|
|
430
430
|
/**
|
|
@@ -434,7 +434,7 @@ class FormComponent extends Component_1.default {
|
|
|
434
434
|
*/
|
|
435
435
|
loadSubForm(fromAttach) {
|
|
436
436
|
var _a, _b, _c, _d, _e;
|
|
437
|
-
if (this.builderMode || this.
|
|
437
|
+
if (this.builderMode || this.conditionallyHidden || (this.isSubFormLazyLoad() && !fromAttach)) {
|
|
438
438
|
return Promise.resolve();
|
|
439
439
|
}
|
|
440
440
|
if (this.hasLoadedForm && !this.isRevisionChanged &&
|
|
@@ -518,7 +518,7 @@ class FormComponent extends Component_1.default {
|
|
|
518
518
|
* @returns {*|boolean} - TRUE if the subform should be submitted, FALSE if it should not.
|
|
519
519
|
*/
|
|
520
520
|
get shouldSubmit() {
|
|
521
|
-
return this.subFormReady && (!this.component.hasOwnProperty('reference') || this.component.reference) && !this.
|
|
521
|
+
return this.subFormReady && (!this.component.hasOwnProperty('reference') || this.component.reference) && !this.conditionallyHidden;
|
|
522
522
|
}
|
|
523
523
|
/**
|
|
524
524
|
* 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
|
}
|
|
@@ -342,9 +342,8 @@ class RadioComponent extends ListComponent_1.default {
|
|
|
342
342
|
label: this.component.valueProperty ? this.itemTemplate(item, valueAtProperty) : this.itemTemplate(item, item, i)
|
|
343
343
|
};
|
|
344
344
|
listData.push(this.templateData[this.component.valueProperty ? valueAtProperty : i]);
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
(!this.isRadio && lodash_1.default.isBoolean(valueAtProperty)))) {
|
|
345
|
+
const value = this.loadedOptions[i].value;
|
|
346
|
+
if (!this.isRadio && (lodash_1.default.isObject(value) || lodash_1.default.isBoolean(value) || lodash_1.default.isUndefined(value))) {
|
|
348
347
|
this.loadedOptions[i].invalid = true;
|
|
349
348
|
}
|
|
350
349
|
});
|
|
@@ -115,6 +115,13 @@ declare class Component extends Element {
|
|
|
115
115
|
*/
|
|
116
116
|
parent: Component;
|
|
117
117
|
_path: string;
|
|
118
|
+
/**
|
|
119
|
+
* Determines if this component is conditionally hidden. Should generally not be set outside of conditional logic pipeline.
|
|
120
|
+
* This is necessary because of clearOnHide behavior that only clears when conditionally hidden - we need to track
|
|
121
|
+
* conditionallyHidden separately from "regular" visibility.
|
|
122
|
+
*/
|
|
123
|
+
_parentConditionallyHidden: any;
|
|
124
|
+
_conditionallyHidden: any;
|
|
118
125
|
/**
|
|
119
126
|
* Determines if this component is visible, or not.
|
|
120
127
|
*/
|
|
@@ -207,6 +214,14 @@ declare class Component extends Element {
|
|
|
207
214
|
* @returns {boolean} - Whether the component is visible or not.
|
|
208
215
|
*/
|
|
209
216
|
get visible(): boolean;
|
|
217
|
+
get conditionallyHidden(): any;
|
|
218
|
+
/**
|
|
219
|
+
* Evaluates whether the component is conditionally hidden (as opposed to intentionally hidden, e.g. via the `hidden` component schema property).
|
|
220
|
+
* @param {object} data - The data object to evaluate the condition against.
|
|
221
|
+
* @param {object} row - The row object to evaluate the condition against.
|
|
222
|
+
* @returns {boolean} - Whether the component is conditionally hidden.
|
|
223
|
+
*/
|
|
224
|
+
checkConditionallyHidden(data?: object, row?: object): boolean;
|
|
210
225
|
set currentForm(instance: any);
|
|
211
226
|
get currentForm(): any;
|
|
212
227
|
_currentForm: any;
|
|
@@ -308,11 +308,18 @@ export default class Component extends Element {
|
|
|
308
308
|
this._path = '';
|
|
309
309
|
// Needs for Nextgen Rules Engine
|
|
310
310
|
this.resetCaches();
|
|
311
|
+
/**
|
|
312
|
+
* Determines if this component is conditionally hidden. Should generally not be set outside of conditional logic pipeline.
|
|
313
|
+
* This is necessary because of clearOnHide behavior that only clears when conditionally hidden - we need to track
|
|
314
|
+
* conditionallyHidden separately from "regular" visibility.
|
|
315
|
+
*/
|
|
316
|
+
this._parentConditionallyHidden = this.options.hasOwnProperty('parentConditionallyHidden') ? this.options.parentConditionallyHidden : false;
|
|
317
|
+
this._conditionallyHidden = this.checkConditionallyHidden(null, data) || this._parentConditionallyHidden;
|
|
311
318
|
/**
|
|
312
319
|
* Determines if this component is visible, or not.
|
|
313
320
|
*/
|
|
314
321
|
this._parentVisible = this.options.hasOwnProperty('parentVisible') ? this.options.parentVisible : true;
|
|
315
|
-
this._visible = this._parentVisible && this.
|
|
322
|
+
this._visible = this._parentVisible && (this.hasCondition() ? !this._conditionallyHidden : !this.component.hidden);
|
|
316
323
|
this._parentDisabled = false;
|
|
317
324
|
/**
|
|
318
325
|
* The reference attribute name for this component
|
|
@@ -381,7 +388,7 @@ export default class Component extends Element {
|
|
|
381
388
|
if (this.allowData && this.key) {
|
|
382
389
|
this.options.name += `[${this.key}]`;
|
|
383
390
|
// If component is visible or not set to clear on hide, set the default value.
|
|
384
|
-
if (this.
|
|
391
|
+
if (!(this.conditionallyHidden && this.component.clearOnHide)) {
|
|
385
392
|
if (!this.hasValue()) {
|
|
386
393
|
if (this.shouldAddDefaultValue) {
|
|
387
394
|
this.dataValue = this.defaultValue;
|
|
@@ -455,7 +462,8 @@ export default class Component extends Element {
|
|
|
455
462
|
}
|
|
456
463
|
init() {
|
|
457
464
|
this.disabled = this.shouldDisabled;
|
|
458
|
-
this.
|
|
465
|
+
this._conditionallyHidden = this.checkConditionallyHidden();
|
|
466
|
+
this._visible = (this.hasCondition() ? !this.conditionallyHidden : !this.component.hidden);
|
|
459
467
|
if (this.component.addons?.length) {
|
|
460
468
|
this.component.addons.forEach((addon) => this.createAddon(addon));
|
|
461
469
|
}
|
|
@@ -573,7 +581,6 @@ export default class Component extends Element {
|
|
|
573
581
|
return;
|
|
574
582
|
}
|
|
575
583
|
this._visible = value;
|
|
576
|
-
this.clearOnHide();
|
|
577
584
|
this.redraw();
|
|
578
585
|
}
|
|
579
586
|
}
|
|
@@ -594,6 +601,21 @@ export default class Component extends Element {
|
|
|
594
601
|
}
|
|
595
602
|
return this._visible && this._parentVisible;
|
|
596
603
|
}
|
|
604
|
+
get conditionallyHidden() {
|
|
605
|
+
return this._conditionallyHidden || this._parentConditionallyHidden;
|
|
606
|
+
}
|
|
607
|
+
/**
|
|
608
|
+
* Evaluates whether the component is conditionally hidden (as opposed to intentionally hidden, e.g. via the `hidden` component schema property).
|
|
609
|
+
* @param {object} data - The data object to evaluate the condition against.
|
|
610
|
+
* @param {object} row - The row object to evaluate the condition against.
|
|
611
|
+
* @returns {boolean} - Whether the component is conditionally hidden.
|
|
612
|
+
*/
|
|
613
|
+
checkConditionallyHidden(data = null, row = null) {
|
|
614
|
+
if (!this.hasCondition()) {
|
|
615
|
+
return false;
|
|
616
|
+
}
|
|
617
|
+
return !this.conditionallyVisible(data, row);
|
|
618
|
+
}
|
|
597
619
|
get currentForm() {
|
|
598
620
|
return this._currentForm;
|
|
599
621
|
}
|
|
@@ -1764,7 +1786,7 @@ export default class Component extends Element {
|
|
|
1764
1786
|
rebuild() {
|
|
1765
1787
|
this.destroy();
|
|
1766
1788
|
this.init();
|
|
1767
|
-
this.visible = this.
|
|
1789
|
+
this.visible = this.hasCondition() ? !this.conditionallyHidden : !this.component.hidden;
|
|
1768
1790
|
return this.redraw();
|
|
1769
1791
|
}
|
|
1770
1792
|
/**
|
|
@@ -1831,8 +1853,8 @@ export default class Component extends Element {
|
|
|
1831
1853
|
conditionallyVisible(data, row) {
|
|
1832
1854
|
data = data || this.rootValue;
|
|
1833
1855
|
row = row || this.data;
|
|
1834
|
-
if (this.builderMode || this.previewMode
|
|
1835
|
-
return
|
|
1856
|
+
if (this.builderMode || this.previewMode) {
|
|
1857
|
+
return true;
|
|
1836
1858
|
}
|
|
1837
1859
|
data = data || (this.root ? this.root.data : {});
|
|
1838
1860
|
return this.checkCondition(row, data);
|
|
@@ -1862,8 +1884,14 @@ export default class Component extends Element {
|
|
|
1862
1884
|
if (!this.builderMode & !this.previewMode && this.fieldLogic(data, row)) {
|
|
1863
1885
|
this.redraw();
|
|
1864
1886
|
}
|
|
1865
|
-
// Check advanced conditions
|
|
1866
|
-
const
|
|
1887
|
+
// Check advanced conditions (and cache the result)
|
|
1888
|
+
const isConditionallyHidden = this.checkConditionallyHidden(data, row) || this._parentConditionallyHidden;
|
|
1889
|
+
if (isConditionallyHidden !== this._conditionallyHidden) {
|
|
1890
|
+
this._conditionallyHidden = isConditionallyHidden;
|
|
1891
|
+
this.clearOnHide();
|
|
1892
|
+
}
|
|
1893
|
+
// Check visibility
|
|
1894
|
+
const visible = (this.hasCondition() ? !this.conditionallyHidden : !this.component.hidden);
|
|
1867
1895
|
if (this.visible !== visible) {
|
|
1868
1896
|
this.visible = visible;
|
|
1869
1897
|
}
|
|
@@ -1973,6 +2001,12 @@ export default class Component extends Element {
|
|
|
1973
2001
|
FormioUtils.setActionProperty(newComponent, action, result, row, data, this);
|
|
1974
2002
|
const property = action.property.value;
|
|
1975
2003
|
if (!_.isEqual(_.get(this.component, property), _.get(newComponent, property))) {
|
|
2004
|
+
// Advanced Logic can modify the component's hidden property; because we track conditionally hidden state
|
|
2005
|
+
// separately from the component's hidden property, and technically this Advanced Logic conditionally hides
|
|
2006
|
+
// a component, we need to set _conditionallyHidden to the new value
|
|
2007
|
+
if (property === 'hidden') {
|
|
2008
|
+
this._conditionallyHidden = newComponent.hidden;
|
|
2009
|
+
}
|
|
1976
2010
|
changed = true;
|
|
1977
2011
|
}
|
|
1978
2012
|
break;
|
|
@@ -1986,7 +2020,7 @@ export default class Component extends Element {
|
|
|
1986
2020
|
component: newComponent,
|
|
1987
2021
|
result,
|
|
1988
2022
|
});
|
|
1989
|
-
if (!_.isEqual(oldValue, newValue) && !(this.component.clearOnHide &&
|
|
2023
|
+
if (!_.isEqual(oldValue, newValue) && !(this.component.clearOnHide && this.conditionallyHidden)) {
|
|
1990
2024
|
this.setValue(newValue);
|
|
1991
2025
|
if (this.viewOnly) {
|
|
1992
2026
|
this.dataValue = newValue;
|
|
@@ -2019,7 +2053,7 @@ export default class Component extends Element {
|
|
|
2019
2053
|
component: newComponent,
|
|
2020
2054
|
result,
|
|
2021
2055
|
}, 'value');
|
|
2022
|
-
if (!_.isEqual(oldValue, newValue) && !(this.component.clearOnHide &&
|
|
2056
|
+
if (!_.isEqual(oldValue, newValue) && !(this.component.clearOnHide && this.conditionallyHidden)) {
|
|
2023
2057
|
this.setValue(newValue);
|
|
2024
2058
|
if (this.viewOnly) {
|
|
2025
2059
|
this.dataValue = newValue;
|
|
@@ -2130,7 +2164,7 @@ export default class Component extends Element {
|
|
|
2130
2164
|
this.component.clearOnHide !== false &&
|
|
2131
2165
|
!this.options.readOnly &&
|
|
2132
2166
|
!this.options.showHiddenFields) {
|
|
2133
|
-
if (
|
|
2167
|
+
if (this.conditionallyHidden) {
|
|
2134
2168
|
this.deleteValue();
|
|
2135
2169
|
}
|
|
2136
2170
|
else if (!this.hasValue() && this.shouldAddDefaultValue) {
|
|
@@ -2392,7 +2426,7 @@ export default class Component extends Element {
|
|
|
2392
2426
|
*/
|
|
2393
2427
|
get dataValue() {
|
|
2394
2428
|
if (!this.key ||
|
|
2395
|
-
(
|
|
2429
|
+
(this.conditionallyHidden && this.component.clearOnHide && !this.rootPristine)) {
|
|
2396
2430
|
return this.emptyValue;
|
|
2397
2431
|
}
|
|
2398
2432
|
if (!this.hasValue() && this.shouldAddDefaultValue) {
|
|
@@ -2411,7 +2445,7 @@ export default class Component extends Element {
|
|
|
2411
2445
|
set dataValue(value) {
|
|
2412
2446
|
if (!this.allowData ||
|
|
2413
2447
|
!this.key ||
|
|
2414
|
-
(
|
|
2448
|
+
(this.conditionallyHidden && this.component.clearOnHide && !this.rootPristine)) {
|
|
2415
2449
|
return;
|
|
2416
2450
|
}
|
|
2417
2451
|
if ((value !== null) && (value !== undefined)) {
|
|
@@ -2731,7 +2765,7 @@ export default class Component extends Element {
|
|
|
2731
2765
|
// If no calculated value or
|
|
2732
2766
|
// hidden and set to clearOnHide (Don't calculate a value for a hidden field set to clear when hidden)
|
|
2733
2767
|
const { clearOnHide } = this.component;
|
|
2734
|
-
const shouldBeCleared =
|
|
2768
|
+
const shouldBeCleared = this.conditionallyHidden && clearOnHide;
|
|
2735
2769
|
const allowOverride = _.get(this.component, 'allowCalculateOverride', false);
|
|
2736
2770
|
if (shouldBeCleared) {
|
|
2737
2771
|
// remove calculated value so that the value is recalculated once component becomes visible
|
|
@@ -3367,7 +3401,7 @@ export default class Component extends Element {
|
|
|
3367
3401
|
// If component definition changed, replace it.
|
|
3368
3402
|
if (!_.isEqual(this.component, newComponent)) {
|
|
3369
3403
|
this.component = newComponent;
|
|
3370
|
-
const visible = this.
|
|
3404
|
+
const visible = this.hasCondition() ? !this.conditionallyHidden : !this.component.hidden;
|
|
3371
3405
|
const disabled = this.shouldDisabled;
|
|
3372
3406
|
// Change states which won't be recalculated during redrawing
|
|
3373
3407
|
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>'),
|