diff --git a/src/utils/utils.js b/src/utils/utils.js index c9d36bd2f4..907d21b581 100644 --- a/src/utils/utils.js +++ b/src/utils/utils.js @@ -299,12 +299,14 @@ function getConditionalPathsRecursive(conditionPaths, data) { export function getComponentActualValue(compPath, data, row) { let value = null; - if (row) { - value = getValue({ data: row }, compPath); - } - if (data && _.isNil(value)) { + if (data) { value = getValue({ data }, compPath); } + + if (row && _.isNil(value)) { + value = getValue({ data: row }, compPath); + } + // FOR-400 - Fix issue where falsey values were being evaluated as show=true if (_.isNil(value) || (_.isObject(value) && _.isEmpty(value))) { value = ''; diff --git a/test/forms/formsWithSimpleConditionals.js b/test/forms/formsWithSimpleConditionals.js new file mode 100644 index 0000000000..2df055ac73 --- /dev/null +++ b/test/forms/formsWithSimpleConditionals.js @@ -0,0 +1,235 @@ +const form1 = { + _id: '672b166eb403d512b0f568bd', + title: 'ECB key issue', + name: 'ecbKeyIssue', + path: 'ecbkeyissue', + type: 'form', + display: 'form', + owner: '672b16f7b403d512b0f56d59', + components: [ + { + label: 'Another container', + tableView: false, + key: 'anotherContainerKey', + type: 'container', + input: true, + components: [ + { + label: + "A select with the same key of a container in tab1. Select the option 'more'", + widget: 'choicesjs', + tableView: true, + data: { + values: [ + { + label: 'less', + value: 'less', + }, + { + label: 'more', + value: 'more', + }, + ], + }, + customOptions: { + searchResultLimit: 100, + fuseOptions: { + threshold: 0.1, + distance: 9000, + }, + }, + validateWhenHidden: false, + key: 'someDuplicatedKey', + type: 'select', + input: true, + }, + { + label: 'Text Field', + applyMaskOn: 'change', + tableView: true, + validateWhenHidden: false, + key: 'textField', + conditional: { + show: true, + conjunction: 'all', + conditions: [ + { + component: 'anotherContainerKey.someDuplicatedKey', + operator: 'isEqual', + value: 'more', + }, + ], + }, + type: 'textfield', + input: true, + }, + { + label: 'Here select yes, value will disappear', + tableView: false, + validateWhenHidden: false, + key: 'additionalContainer', + conditional: { + show: true, + conjunction: 'all', + conditions: [ + { + component: 'someDuplicatedKey', + operator: 'isEqual', + value: 'more', + }, + ], + }, + type: 'container', + input: true, + components: [ + { + label: 'Number', + applyMaskOn: 'change', + mask: false, + tableView: false, + delimiter: false, + requireDecimal: false, + inputFormat: 'plain', + truncateMultipleSpaces: false, + validateWhenHidden: false, + key: 'number', + type: 'number', + input: true, + }, + ], + }, + ], + }, + { + label: 'duplicate key', + applyMaskOn: 'change', + tableView: true, + validateWhenHidden: false, + key: 'someDuplicatedKey', + type: 'textfield', + input: true, + }, + { + type: 'button', + label: 'Submit', + key: 'submit', + disableOnInvalid: true, + input: true, + tableView: false, + }, + ], + machineName: 'testecb-izutenexavvxnws:ecbKeyIssue', + project: '672b1664b403d512b0f564e0', + created: '2024-11-06T07:10:38.132Z', + modified: '2024-11-06T08:38:05.103Z', +}; + +const form2 = { + _id: '672b21b4b403d512b0f58351', + title: 'test datagrid', + name: 'testDatagrid', + path: 'testdatagrid', + type: 'form', + display: 'form', + owner: '637b2e6b48c1227e60b1f910', + components: [ + { + label: 'Data Grid', + reorder: false, + addAnotherPosition: 'bottom', + layoutFixed: false, + enableRowGroups: false, + initEmpty: false, + tableView: false, + defaultValue: [{}], + validateWhenHidden: false, + key: 'dataGrid', + type: 'datagrid', + input: true, + components: [ + { + label: 'Container', + tableView: false, + validateWhenHidden: false, + key: 'container', + type: 'container', + input: true, + components: [ + { + label: 'Text Field', + applyMaskOn: 'change', + tableView: true, + validateWhenHidden: false, + key: 'textField', + type: 'textfield', + input: true, + }, + ], + }, + { + label: 'Number', + applyMaskOn: 'change', + mask: false, + tableView: false, + delimiter: false, + requireDecimal: false, + inputFormat: 'plain', + truncateMultipleSpaces: false, + validateWhenHidden: false, + key: 'number', + conditional: { + show: true, + conjunction: 'any', + conditions: [ + { + component: 'dataGrid.container.textField', + operator: 'isEqual', + value: '5', + }, + { + component: 'container.textField', + operator: 'isEqual', + value: '6', + }, + ], + }, + type: 'number', + input: true, + }, + ], + }, + { + label: 'Container', + tableView: false, + validateWhenHidden: false, + key: 'container', + type: 'container', + input: true, + components: [ + { + label: 'Text Field', + applyMaskOn: 'change', + tableView: true, + validateWhenHidden: false, + key: 'textField', + type: 'textfield', + input: true, + }, + ], + }, + { + type: 'button', + label: 'Submit', + key: 'submit', + disableOnInvalid: true, + input: true, + tableView: false, + }, + ], + project: '672b1664b403d512b0f564e0', + created: '2024-11-06T07:58:44.344Z', + modified: '2024-11-06T08:01:29.344Z', + machineName: 'testecb-izutenexavvxnws:testDatagrid', +}; + +export default { form1, form2 }; diff --git a/test/unit/Webform.unit.js b/test/unit/Webform.unit.js index c67beebed3..28cb768d2f 100644 --- a/test/unit/Webform.unit.js +++ b/test/unit/Webform.unit.js @@ -85,6 +85,7 @@ import wizardWithRequiredFields from '../forms/wizardWithRequiredFields'; import webformWithNestedWizard from '../forms/webformWIthNestedWizard'; import formWithUniqueValidation from '../forms/formWithUniqueValidation.js'; import formWithConditionalEmail from '../forms/formWithConditionalEmail.js'; +import formsWithSimpleConditionals from '../forms/formsWithSimpleConditionals.js'; const SpySanitize = sinon.spy(FormioUtils, 'sanitize'); if (_.has(Formio, 'Components.setComponents')) { @@ -94,6 +95,80 @@ if (_.has(Formio, 'Components.setComponents')) { /* eslint-disable max-statements */ describe('Webform tests', function() { this.retries(3); + it('Should show fields correctly if there are 2 components with the same key in the form', function(done) { + const formElement = document.createElement('div'); + const form = new Webform(formElement); + + form.setForm(formsWithSimpleConditionals.form1).then(() => { + const compWithDuplicatedKey1 = form.getComponent('anotherContainerKey.someDuplicatedKey'); + const compWithDuplicatedKey2 = form.getComponent('someDuplicatedKey'); + const conditionalCompShownOnDupl1 = form.getComponent('anotherContainerKey.textField'); + const conditionalCompShownOnDupl2 = form.getComponent('anotherContainerKey.additionalContainer'); + assert.equal(conditionalCompShownOnDupl1.visible, false); + assert.equal(conditionalCompShownOnDupl2.visible, false); + compWithDuplicatedKey1.setValue('more'); + + setTimeout(() => { + assert.equal(conditionalCompShownOnDupl1.visible, true); + assert.equal(conditionalCompShownOnDupl2.visible, false); + + compWithDuplicatedKey2.setValue('more'); + + setTimeout(() => { + assert.equal(conditionalCompShownOnDupl1.visible, true); + assert.equal(conditionalCompShownOnDupl2.visible, true); + + compWithDuplicatedKey1.setValue('less'); + setTimeout(() => { + assert.equal(conditionalCompShownOnDupl1.visible, false); + assert.equal(conditionalCompShownOnDupl2.visible, true); + done(); + }, 300); + }, 300); + }, 300); + }).catch((err) => done(err)); + }); + + it('Should show fields correctly inside dataGrid row if there are components with the same key in the form and dataGrid component visibility depennds on component inside row and outside dataGrid', function(done) { + const formElement = document.createElement('div'); + const form = new Webform(formElement); + + form.setForm(formsWithSimpleConditionals.form2).then(() => { + const compWithDuplicatedKey1 = form.getComponent('container.textField'); + const compWithDuplicatedKey2 = form.getComponent('dataGrid.container.textField')[0]; + const conditionalCompShownOnDupl1Or2 = form.getComponent('dataGrid.number')[0]; + const dataGrid = form.getComponent('dataGrid'); + assert.equal(conditionalCompShownOnDupl1Or2.visible, false); + compWithDuplicatedKey1.setValue('6'); + + setTimeout(() => { + assert.equal(conditionalCompShownOnDupl1Or2.visible, true); + compWithDuplicatedKey1.setValue('7'); + + setTimeout(() => { + const conditionalCompShownOnDupl1Or2 = form.getComponent('dataGrid.number')[0]; + assert.equal(conditionalCompShownOnDupl1Or2.visible, false); + compWithDuplicatedKey2.setValue('5'); + setTimeout(() => { + assert.equal(conditionalCompShownOnDupl1Or2.visible, true); + dataGrid.addRow(); + setTimeout(() => { + const conditionalComp2ShownOnDupl1Or2 = form.getComponent('dataGrid.number')[1]; + assert.equal(conditionalCompShownOnDupl1Or2.visible, true); + assert.equal(conditionalComp2ShownOnDupl1Or2.visible, false); + compWithDuplicatedKey1.setValue('6'); + setTimeout(() => { + assert.equal(conditionalCompShownOnDupl1Or2.visible, true); + assert.equal(conditionalComp2ShownOnDupl1Or2.visible, true); + done(); + }, 400); + }, 400); + }, 400); + }, 400); + }, 300); + }).catch((err) => done(err)); + }); + it('Should validate email input when it is simple conditionally visible', done => { const formElement = document.createElement('div'); Formio.createForm(formElement, formWithConditionalEmail)