Skip to content

Commit

Permalink
Merge pull request #139 from formio/FIO-8810-fixed-neted-form-validat…
Browse files Browse the repository at this point in the history
…ion-without-reference-attached

FIO-8810: fixed an issue where user unables to resubmit (change) the form with several levels of nested forms with required fields
  • Loading branch information
brendanbond authored Aug 24, 2024
2 parents d596125 + db39577 commit 7e1bebc
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 4 deletions.
97 changes: 97 additions & 0 deletions src/process/__tests__/process.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2831,6 +2831,103 @@ describe('Process Tests', () => {
});
})

it('Should allow the submission to go through without errors if there is no the subform reference value', async () => {
const form = {
_id: '66bc5cff7ca1729623a182db',
title: 'form2',
name: 'form2',
path: 'form2',
type: 'resource',
display: 'form',
owner: '637b2e6b48c1227e60b1f910',
components: [
{
label: 'Text Field - form2',
applyMaskOn: 'change',
tableView: true,
validate: { required: true },
validateWhenHidden: false,
key: 'textFieldForm2',
type: 'textfield',
input: true,
},
{
label: 'Form',
tableView: true,
form: '66bc5ccd7ca1729623a18063',
useOriginalRevision: false,
key: 'form',
type: 'form',
input: true,
components: [
{
label: 'Text Field form1',
applyMaskOn: 'change',
tableView: true,
validate: { required: true },
validateWhenHidden: false,
key: 'textFieldForm1',
type: 'textfield',
input: true,
},
{
type: 'button',
label: 'Submit',
key: 'submit',
disableOnInvalid: true,
input: true,
tableView: false,
},
],
},
{
type: 'button',
label: 'Submit',
key: 'submit',
disableOnInvalid: true,
input: true,
tableView: false,
},
],
project: '669e1c67a40e327e67e7ce55',
_vid: 0,
esign: {},
created: '2024-08-14T07:30:07.953Z',
modified: '2024-08-14T10:09:13.201Z',
machineName: 'qzdhayddccjauyr:form2',
__v: 1,
};

const submission = {
data: { textFieldForm2: '1', form: { _id: '66c455fc0f00757fd4b0e79b' } },
owner: '637b2e6b48c1227e60b1f910',
access: [],
_fvid: 0,
state: 'submitted',
_id: '66c455fc0f00757fd4b0e79d',
form: '66bc5cff7ca1729623a182db',
};

const errors: any = [];
const context = {
form,
submission,
data: submission.data,
components: form.components,
processors: ProcessTargets.submission,
scope: { errors },
config: {
server: true,
},
};
processSync(context);
submission.data = context.data;
context.processors = ProcessTargets.evaluator;
processSync(context);
assert.equal(context.scope.errors.length, 0);
assert.deepEqual(context.data.form, { _id: '66c455fc0f00757fd4b0e79b', data: {} })
});

describe('Required component validation in nested form in DataGrid/EditGrid', () => {
const nestedForm = {
key: 'form',
Expand Down
14 changes: 10 additions & 4 deletions src/utils/formUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -278,8 +278,11 @@ export const eachComponentDataAsync = async (
return true;
}
if (isComponentModelType(component, 'dataObject')) {
// No need to bother processing all the children data if there is no data for this form.
if (has(data, component.path)) {
// No need to bother processing all the children data if there is no data for this form or the reference value has not been loaded.
const nestedFormValue: any = get(data, component.path);
const noReferenceAttached = nestedFormValue?._id && isEmpty(nestedFormValue.data) && !has(nestedFormValue, 'form');
const shouldProcessNestedFormData = nestedFormValue?._id ? !noReferenceAttached : has(data, component.path);
if (shouldProcessNestedFormData) {
// For nested forms, we need to reset the "data" and "path" objects for all of the children components, and then re-establish the data when it is done.
const childPath: string = componentDataPath(component, path, compPath);
const childData: any = get(data, childPath, null);
Expand Down Expand Up @@ -331,8 +334,11 @@ export const eachComponentData = (
return true;
}
if (isComponentModelType(component, 'dataObject')) {
// No need to bother processing all the children data if there is no data for this form.
if (has(data, component.path)) {
// No need to bother processing all the children data if there is no data for this form or the reference value has not been loaded.
const nestedFormValue: any = get(data, component.path);
const noReferenceAttached = nestedFormValue?._id && isEmpty(nestedFormValue.data) && !has(nestedFormValue, 'form');
const shouldProcessNestedFormData = nestedFormValue?._id ? !noReferenceAttached : has(data, component.path);
if (shouldProcessNestedFormData) {
// For nested forms, we need to reset the "data" and "path" objects for all of the children components, and then re-establish the data when it is done.
const childPath: string = componentDataPath(component, path, compPath);
const childData: any = get(data, childPath, {});
Expand Down

0 comments on commit 7e1bebc

Please sign in to comment.