diff --git a/src/components/_classes/component/Component.js b/src/components/_classes/component/Component.js index 1c05119179..6e9d8a55af 100644 --- a/src/components/_classes/component/Component.js +++ b/src/components/_classes/component/Component.js @@ -511,6 +511,18 @@ export default class Component extends Element { return false; } + + hasCondionallyHiddenLayoutParent() { + let currentParent = this.parent; + while (currentParent) { + if (currentParent._conditionallyHidden && FormioUtils.isLayoutComponent(currentParent) && currentParent.component.clearOnHide === true) { + return true; + } + currentParent = currentParent.parent; + } + return false + } + parentConditionallyHidden() { let currentParent = this.parent; while (currentParent) { @@ -822,7 +834,7 @@ export default class Component extends Element { this._conditionallyClear = true; return this._conditionallyClear; } - this._conditionallyClear = this.hasSetValue ? false : this.parentShouldConditionallyClear(); + this._conditionallyClear = this.hasSetValue ? this.hasCondionallyHiddenLayoutParent() : this.parentShouldConditionallyClear(); return this._conditionallyClear; } diff --git a/src/components/fieldset/Fieldset.js b/src/components/fieldset/Fieldset.js index 9b71fe87e0..131dfecb2d 100644 --- a/src/components/fieldset/Fieldset.js +++ b/src/components/fieldset/Fieldset.js @@ -8,6 +8,7 @@ export default class FieldsetComponent extends NestedComponent { type: 'fieldset', legend: '', components: [], + clearOnHide: false, input: false, persistent: false }, ...extend); diff --git a/test/forms/clearOnHideInsideLayoutComponent.js b/test/forms/clearOnHideInsideLayoutComponent.js new file mode 100644 index 0000000000..472d479d62 --- /dev/null +++ b/test/forms/clearOnHideInsideLayoutComponent.js @@ -0,0 +1,85 @@ +export default { + "type": "form", + "components": [ + { + "label": "Checkbox", + "tableView": false, + "defaultValue": true, + "validateWhenHidden": false, + "key": "checkbox", + "type": "checkbox", + "input": true + }, + { + "label": "Panel", + "collapsible": false, + "key": "panel", + "conditional": { + "show": true, + "conjunction": "all", + "conditions": [ + { + "component": "checkbox", + "operator": "isEqual", + "value": true + } + ] + }, + "type": "panel", + "input": false, + "tableView": false, + "components": [ + { + "label": "Text Field", + "applyMaskOn": "change", + "tableView": true, + "validateWhenHidden": false, + "key": "textFieldInPanel", + "type": "textfield", + "input": true + } + ] + }, + { + "label": "", + "key": "fieldset", + "conditional": { + "show": true, + "conjunction": "all", + "conditions": [ + { + "component": "checkbox", + "operator": "isEqual", + "value": true + } + ] + }, + "type": "fieldset", + "input": false, + "tableView": false, + "components": [ + { + "label": "Text Field", + "applyMaskOn": "change", + "tableView": true, + "validateWhenHidden": false, + "key": "textFieldInFieldset", + "type": "textfield", + "input": true + } + ] + }, + { + "type": "button", + "label": "Submit", + "key": "submit", + "disableOnInvalid": true, + "input": true, + "tableView": false + } + ], + "title": "clearOnHide", + "display": "form", + "name": "clearOnHide", + "path": "clearonhide" +} diff --git a/test/unit/Webform.unit.js b/test/unit/Webform.unit.js index b9e2677a27..883d1e183b 100644 --- a/test/unit/Webform.unit.js +++ b/test/unit/Webform.unit.js @@ -94,6 +94,7 @@ import simpleController from '../forms/formWithSimpleController.js'; import formWithHiddenComponents from '../forms/formWithHiddenComponents.js'; import formWithShowAsString from '../forms/formWithShowAsString.js'; import formWithMergeComponentSchemaAndCustomLogic from '../forms/formWithMergeComponentSchemaAndCustomLogic.js'; +import clearOnHideInsideLayoutComponent from '../forms/clearOnHideInsideLayoutComponent.js'; import formWithServerValidation from '../forms/formWithServerValidation.js'; const SpySanitize = sinon.spy(FormioUtils, 'sanitize'); @@ -2419,6 +2420,75 @@ describe('Webform tests', function() { }); }); + + it('Should not delete value of component inside parent conditionally hidden layout component by default', function(done) { + const formElement = document.createElement('div'); + const form = new Webform(formElement); + form.setForm(clearOnHideInsideLayoutComponent).then(() => { + const visibleData = { + data: { + checkbox: true, + textFieldInPanel: 'some text in panel', + textFieldInFieldset: 'some text in fieldset', + submit: false + } + }; + + const textFieldInPanel = form.getComponent('textFieldInPanel'); + textFieldInPanel.setValue('some text in panel'); + const textFieldInFieldset = form.getComponent('textFieldInFieldset'); + textFieldInFieldset.setValue('some text in fieldset'); + setTimeout(() => { + assert.deepEqual(form.data, visibleData.data); + const checkbox = form.getComponent('checkbox'); + checkbox.setValue(false); + setTimeout(() => { + assert.equal(form.data.textFieldInPanel, 'some text in panel'); + assert.equal(form.data.textFieldInFieldset, 'some text in fieldset'); + done(); + }, 250); + }, 250); + }); + }); + + it('Should delete value of component inside parent conditionally hidden layout component if clearOnHide is set to true', function(done) { + const formElement = document.createElement('div'); + const form = new Webform(formElement); + const testForm = fastCloneDeep(clearOnHideInsideLayoutComponent); + _.set(testForm, 'components[1].clearOnHide', true); + _.set(testForm, 'components[2].clearOnHide', true) + form.setForm(testForm).then(() => { + const visibleData = { + data: { + checkbox: true, + textFieldInPanel: 'some text in panel', + textFieldInFieldset: 'some text in fieldset', + submit: false + } + }; + + const hiddenData = { + data: { + checkbox: false, + submit: false + } + }; + const textFieldInPanel = form.getComponent('textFieldInPanel'); + textFieldInPanel.setValue('some text in panel'); + const textFieldInFieldset = form.getComponent('textFieldInFieldset'); + textFieldInFieldset.setValue('some text in fieldset'); + setTimeout(() => { + assert.deepEqual(form.data, visibleData.data); + const checkbox = form.getComponent('checkbox'); + checkbox.setValue(false); + setTimeout(() => { + assert.deepEqual(form.data, hiddenData.data); + done(); + }, 250); + }, 250); + }); + }); + const formElement = document.createElement('div'); const checkForErrors = function(form, flags = {}, submission, numErrors, done) { form.setSubmission(submission, flags).then(() => {