diff --git a/src/process/__tests__/process.test.ts b/src/process/__tests__/process.test.ts index 81e25183..0a7f8873 100644 --- a/src/process/__tests__/process.test.ts +++ b/src/process/__tests__/process.test.ts @@ -2780,6 +2780,112 @@ describe('Process Tests', () => { }); }); + it('Should properly validate comopnents inside Data Components with Advanced logic', async () => { + const form = { + display: 'form', + components: [ + { + label: 'Data Grid', + reorder: false, + addAnotherPosition: 'bottom', + layoutFixed: false, + enableRowGroups: false, + initEmpty: false, + tableView: false, + key: 'dataGrid', + type: 'datagrid', + input: true, + components: [ + { + label: 'Text Field1', + tableView: true, + key: 'textField1', + logic: [ + { + name: 'logic1', + trigger: { + type: 'javascript', + javascript: 'result = !row.textField2;' + }, + actions: [ + { + name: 'action1', + type: 'property', + property: { + label: 'Required', + value: 'validate.required', + type: 'boolean' + }, + state: true + } + ] + } + ], + type: 'textfield', + input: true + }, + { + label: 'Text Field2', + tableView: true, + key: 'textField2', + logic: [ + { + name: 'logic2', + trigger: { + type: 'javascript', + javascript: 'result = !row.textField1;' + }, + actions: [ + { + name: 'action2', + type: 'property', + property: { + label: 'Required', + value: 'validate.required', + type: 'boolean' + }, + state: true + } + ] + } + ], + type: 'textfield', + input: true + } + ] + } + ] + }; + const submission ={ + data: { + dataGrid: [ + { + textField1: 'test', + textField2: '' + }, + { + textField1: '', + textField2: 'test' + } + ] + } + } + const context = { + form, + submission, + data: submission.data, + components: form.components, + processors: ProcessTargets.evaluator, + scope: {}, + config: { + server: true, + }, + }; + processSync(context); + expect(context.components[0].components).to.deep.equal(form.components[0].components); + expect((context.scope as ValidationScope).errors).to.have.length(0); +}) + describe('Required component validation in nested form in DataGrid/EditGrid', () => { const nestedForm = { key: 'form', diff --git a/src/utils/logic.ts b/src/utils/logic.ts index 2dc7efce..ee0c27a4 100644 --- a/src/utils/logic.ts +++ b/src/utils/logic.ts @@ -3,6 +3,7 @@ import { checkCustomConditional, checkJsonConditional, checkLegacyConditional, c import { LogicActionCustomAction, LogicActionMergeComponentSchema, LogicActionProperty, LogicActionPropertyBoolean, LogicActionPropertyString, LogicActionValue } from "types/AdvancedLogic"; import { get, set, clone, isEqual, assign } from 'lodash'; import { evaluate, interpolate } from 'modules/jsonlogic'; +import { fastCloneDeep } from "./fastCloneDeep"; export const hasLogic = (context: LogicContext): boolean => { const { component } = context; @@ -46,7 +47,10 @@ export function setActionBooleanProperty(context: LogicContext, action: LogicAct const currentValue = get(component, property, false).toString(); const newValue = action.state.toString(); if (currentValue !== newValue) { - set(component, property, newValue === 'true'); + const newComponent = fastCloneDeep(component); + set(newComponent, property, newValue === 'true'); + set(context, 'component', newComponent); + // If this is "logic" forcing a component to set hidden property, then we will set the "conditionallyHidden" // flag which will trigger the clearOnHide functionality. @@ -61,12 +65,12 @@ export function setActionBooleanProperty(context: LogicContext, action: LogicAct return cond.path === path }); if (conditionalyHidden) { - conditionalyHidden.conditionallyHidden = component.hidden; + conditionalyHidden.conditionallyHidden = newComponent.hidden; } else { (scope as any).conditionals.push({ path, - conditionallyHidden: component.hidden, + conditionallyHidden: newComponent.hidden, }); } }