diff --git a/src/process/__tests__/fixtures/index.ts b/src/process/__tests__/fixtures/index.ts index 2fb8f5bc..0e682a75 100644 --- a/src/process/__tests__/fixtures/index.ts +++ b/src/process/__tests__/fixtures/index.ts @@ -10,6 +10,7 @@ import forDataGridRequired from './forDataGridRequired.json'; import data1a from './data1a.json'; import form1 from './form1.json'; import subs from './subs.json'; +import requiredFieldInsideEditGrid from './requiredFieldInsideConditionalEditGrid.json'; import formWithDefaultValues from './componentsWithDefaultValues.json'; export { @@ -25,5 +26,6 @@ export { data1a, form1, subs, + requiredFieldInsideEditGrid, formWithDefaultValues, }; diff --git a/src/process/__tests__/fixtures/requiredFieldInsideConditionalEditGrid.json b/src/process/__tests__/fixtures/requiredFieldInsideConditionalEditGrid.json new file mode 100644 index 00000000..0e7cc9ae --- /dev/null +++ b/src/process/__tests__/fixtures/requiredFieldInsideConditionalEditGrid.json @@ -0,0 +1,91 @@ +[{ + "key": "selectGrids", + "type": "radio", + "input": true, + "label": "Select grids", + "inline": false, + "values": [{ + "label": "Show grid 1", + "value": "showGrid1", + "shortcut": "" + }, + { + "label": "Show grid 2", + "value": "showGrid2", + "shortcut": "" + } + ], + "tableView": false, + "validateWhenHidden": false, + "optionsLabelPosition": "right" + }, + { + "key": "grid2", + "type": "editgrid", + "input": true, + "label": "Grid 2", + "rowDrafts": false, + "tableView": false, + "components": [{ + "label": "Checkbox", + "tableView": false, + "validateWhenHidden": false, + "key": "checkbox", + "type": "checkbox", + "input": true + }, + { + "label": "Text Field", + "applyMaskOn": "change", + "tableView": true, + "validate": { + "required": true + }, + "validateWhenHidden": false, + "key": "textField", + "conditional": { + "show": true, + "conjunction": "all", + "conditions": [{ + "component": "grid2.checkbox", + "operator": "isEqual", + "value": true + }] + }, + "type": "textfield", + "input": true + }, + { + "key": "requiredField", + "type": "textfield", + "input": true, + "label": "Required field", + "validate": { + "required": true + }, + "tableView": true, + "applyMaskOn": "change", + "validateWhenHidden": false + } + ], + "conditional": { + "show": true, + "conditions": [{ + "value": "showGrid2", + "operator": "isEqual", + "component": "selectGrids" + }], + "conjunction": "all" + }, + "displayAsTable": false, + "validateWhenHidden": false + }, + { + "key": "submit", + "type": "button", + "input": true, + "label": "Submit", + "tableView": false, + "disableOnInvalid": true + } +] \ No newline at end of file diff --git a/src/process/__tests__/process.test.ts b/src/process/__tests__/process.test.ts index fd99d3ee..29e53758 100644 --- a/src/process/__tests__/process.test.ts +++ b/src/process/__tests__/process.test.ts @@ -14,6 +14,7 @@ import { skipValidForConditionallyHiddenComp, skipValidForLogicallyHiddenComp, skipValidWithHiddenParentComp, + requiredFieldInsideEditGrid, formWithDefaultValues, } from './fixtures'; import _ from 'lodash'; @@ -6622,5 +6623,27 @@ describe('Process Tests', function () { processSync(context); assert.equal(!!context.data.textField, false); }); + + it('Should not show validation errors for required component inside conditionally hidden editGrid', async function () { + const components = requiredFieldInsideEditGrid; + const submission = { + data: { + selectGrids: '', + submit: true, + }, + }; + const context = { + submission, + data: submission.data, + components, + processors: ProcessTargets.submission, + scope: {} as { errors: Record[] }, + }; + processSync(context); + submission.data = context.data; + context.processors = ProcessTargets.evaluator; + processSync(context); + expect(context.scope.errors.length).to.equal(0); + }); }); }); diff --git a/src/utils/formUtil/eachComponentData.ts b/src/utils/formUtil/eachComponentData.ts index 576dae33..02b3d690 100644 --- a/src/utils/formUtil/eachComponentData.ts +++ b/src/utils/formUtil/eachComponentData.ts @@ -36,6 +36,7 @@ export const eachComponentData = ( local: boolean = false, parent?: Component, parentPaths?: ComponentPaths, + noScopeReset?: boolean, ) => { if (!components) { return; @@ -56,7 +57,9 @@ export const eachComponentData = ( compPaths, ) === true ) { - resetComponentScope(component); + if (!noScopeReset) { + resetComponentScope(component); + } return true; } if (isComponentNestedDataType(component)) { @@ -81,6 +84,7 @@ export const eachComponentData = ( local, component, compPaths, + noScopeReset, ); } } else if (includeAll || isUndefined(value)) { @@ -92,13 +96,18 @@ export const eachComponentData = ( local, component, compPaths, + noScopeReset, ); } - resetComponentScope(component); + if (!noScopeReset) { + resetComponentScope(component); + } return true; } else { if (!includeAll && !shouldProcessComponent(component, row, value)) { - resetComponentScope(component); + if (!noScopeReset) { + resetComponentScope(component); + } return true; } eachComponentData( @@ -109,15 +118,27 @@ export const eachComponentData = ( local, component, compPaths, + noScopeReset, ); } - resetComponentScope(component); + if (!noScopeReset) { + resetComponentScope(component); + } return true; } else if (!component.type || getModelType(component) === 'none') { const info = componentInfo(component); if (info.hasColumns) { (component as HasColumns).columns.forEach((column: any) => - eachComponentData(column.components, data, fn, includeAll, local, component, compPaths), + eachComponentData( + column.components, + data, + fn, + includeAll, + local, + component, + compPaths, + noScopeReset, + ), ); } else if (info.hasRows) { (component as HasRows).rows.forEach((row: any) => { @@ -131,6 +152,7 @@ export const eachComponentData = ( local, component, compPaths, + noScopeReset, ), ); } @@ -144,12 +166,17 @@ export const eachComponentData = ( local, component, compPaths, + noScopeReset, ); } - resetComponentScope(component); + if (!noScopeReset) { + resetComponentScope(component); + } return true; } - resetComponentScope(component); + if (!noScopeReset) { + resetComponentScope(component); + } return false; }, true, diff --git a/src/utils/formUtil/eachComponentDataAsync.ts b/src/utils/formUtil/eachComponentDataAsync.ts index 246448d1..35bfd62e 100644 --- a/src/utils/formUtil/eachComponentDataAsync.ts +++ b/src/utils/formUtil/eachComponentDataAsync.ts @@ -28,6 +28,7 @@ export const eachComponentDataAsync = async ( local: boolean = false, parent?: Component, parentPaths?: ComponentPaths, + noScopeReset?: boolean, ) => { if (!components) { return; @@ -53,7 +54,9 @@ export const eachComponentDataAsync = async ( compParent, )) === true ) { - resetComponentScope(component); + if (!noScopeReset) { + resetComponentScope(component); + } return true; } if (isComponentNestedDataType(component)) { @@ -75,6 +78,7 @@ export const eachComponentDataAsync = async ( local, component, compPaths, + noScopeReset, ); } } else if (includeAll) { @@ -86,13 +90,18 @@ export const eachComponentDataAsync = async ( local, component, compPaths, + noScopeReset, ); } - resetComponentScope(component); + if (!noScopeReset) { + resetComponentScope(component); + } return true; } else { if (!includeAll && !shouldProcessComponent(component, row, value)) { - resetComponentScope(component); + if (!noScopeReset) { + resetComponentScope(component); + } return true; } await eachComponentDataAsync( @@ -103,9 +112,12 @@ export const eachComponentDataAsync = async ( local, component, compPaths, + noScopeReset, ); } - resetComponentScope(component); + if (!noScopeReset) { + resetComponentScope(component); + } return true; } else if (!component.type || getModelType(component) === 'none') { const info = componentInfo(component); @@ -120,6 +132,7 @@ export const eachComponentDataAsync = async ( local, component, compPaths, + noScopeReset, ); } } else if (info.hasRows) { @@ -135,6 +148,7 @@ export const eachComponentDataAsync = async ( local, component, compPaths, + noScopeReset, ); } } @@ -148,12 +162,17 @@ export const eachComponentDataAsync = async ( local, component, compPaths, + noScopeReset, ); } - resetComponentScope(component); + if (!noScopeReset) { + resetComponentScope(component); + } return true; } - resetComponentScope(component); + if (!noScopeReset) { + resetComponentScope(component); + } return false; }, true, diff --git a/src/utils/formUtil/index.ts b/src/utils/formUtil/index.ts index 05a4f8c7..379d9ca0 100644 --- a/src/utils/formUtil/index.ts +++ b/src/utils/formUtil/index.ts @@ -511,6 +511,10 @@ export function getComponentFromPath( componentMatches(component, paths || {}, path, dataIndex, matches); }, includeAll, + false, + undefined, + undefined, + true, ); } else { eachComponent(