Skip to content

Commit

Permalink
FIO-9247 fixed triggering custom validation inside Edit Grid
Browse files Browse the repository at this point in the history
  • Loading branch information
HannaKurban committed Oct 25, 2024
1 parent 47de51a commit 21c1482
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 13 deletions.
16 changes: 7 additions & 9 deletions src/components/editgrid/EditGrid.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import {
const EditRowState = {
New: 'new',
Editing: 'editing',
Saving: 'saving',
Saved: 'saved',
Viewing: 'viewing',
Removed: 'removed',
Expand Down Expand Up @@ -952,11 +951,6 @@ export default class EditGridComponent extends NestedArrayComponent {
editRow.components.forEach((comp) => comp.setPristine(false));
}

// Mark the row with a 'Saving' state to trigger validation for future row changes
if (editRow.state === EditRowState.New) {
editRow.state = EditRowState.Saving;
}

const errors = this.validateRow(editRow, true);

if (!this.component.rowDrafts) {
Expand All @@ -971,7 +965,7 @@ export default class EditGridComponent extends NestedArrayComponent {
this.root.focusedComponent = null;
}
switch (editRow.state) {
case EditRowState.Saving: {
case EditRowState.New: {
const newIndex = dataValue.length;
dataValue.push(editRow.data);
editRow.components.forEach(component=>component.rowIndex = newIndex);
Expand Down Expand Up @@ -1165,7 +1159,7 @@ export default class EditGridComponent extends NestedArrayComponent {

shouldValidateRow(editRow, dirty, fromSubmission) {
return this.shouldValidateDraft(editRow) ||
editRow.state === EditRowState.Saving ||
editRow.state === EditRowState.New ||
editRow.state === EditRowState.Editing ||
editRow.alerts ||
fromSubmission ||
Expand All @@ -1181,7 +1175,7 @@ export default class EditGridComponent extends NestedArrayComponent {
editGridValue[editRow.rowIndex] = editRow.data;
_.set(rootValue, this.path, editGridValue);
const validationProcessorProcess = (context) => this.validationProcessor(context, { dirty, silentCheck });
editRow.errors = processSync({
const errors = processSync({
components: fastCloneDeep(this.component.components).map((component) => {
component.parentPath = `${this.path}[${editRow.rowIndex}]`;
return component;
Expand All @@ -1198,6 +1192,10 @@ export default class EditGridComponent extends NestedArrayComponent {
}
]
}).errors;

editRow.errors = (this.component.modal || this.component.rowDrafts)
? errors
: errors.filter((err) => _.find(this.visibleErrors, ['component.id', err.component.id]));
}

// TODO: this is essentially running its own custom validation and should be moved into a validation rule
Expand Down
43 changes: 40 additions & 3 deletions test/unit/EditGrid.unit.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
comp16,
comp17,
comp19,
comp20,
withOpenWhenEmptyAndConditions,
compOpenWhenEmpty,
compWithCustomDefaultValue,
Expand Down Expand Up @@ -1239,7 +1240,7 @@ describe('EditGrid Component', () => {
setTimeout(() => {
assert.equal(!!firstRowTextField.errors, true);
assert.equal(editGrid.editRows[0].errors.length, 1);
assert.equal(editGrid.editRows[0].state, 'saving');
assert.equal(editGrid.editRows[0].state, 'new');

document.innerHTML = '';
done();
Expand Down Expand Up @@ -1444,7 +1445,7 @@ describe('EditGrid Component', () => {
setTimeout(() => {
assert.equal(!!firstRowTextField.errors, true);
assert.equal(editGrid.editRows[0].errors.length, 1);
assert.equal(editGrid.editRows[0].state, 'saving');
assert.equal(editGrid.editRows[0].state, 'new');

document.innerHTML = '';
done();
Expand All @@ -1454,6 +1455,42 @@ describe('EditGrid Component', () => {
}).catch(done);
});

it('Should trigger validation onChange before attempt to save', (done) => {
const form = _.cloneDeep(comp20);
const element = document.createElement('div');

Formio.createForm(element, form).then(form => {
const rootTextField = form.getComponent('text');
rootTextField.setValue('test');
const editGrid = form.getComponent('editGrid');
const clickEvent = new Event('click');
editGrid.refs['editgrid-editGrid-addRow'][0].dispatchEvent(clickEvent);

setTimeout(() => {
const egRowTextField = editGrid.components[0];

const inputEvent = new Event('input');
const textFieldEGInput = egRowTextField.refs.input[0];

textFieldEGInput.value = 'te';
textFieldEGInput.dispatchEvent(inputEvent);

setTimeout(() => {
assert.equal(editGrid.editRows[0].errors.length, 1, 'Should include custom validation error');
assert.equal(editGrid.editRows[0].errors[0].message, 'data must match root textfield');
textFieldEGInput.value = 'test';
textFieldEGInput.dispatchEvent(inputEvent);

setTimeout(() => {
assert.equal(editGrid.editRows[0].errors.length, 0, 'Should not include custom validation error');
document.innerHTML = '';
done();
}, 300);
}, 300);
}, 300)
}).catch(done);
});

it('Should not allow to save invalid row when there are required components inside columns in the editGrod row', (done) => {
const formElement = document.createElement('div');
const form = new Webform(formElement);
Expand All @@ -1471,7 +1508,7 @@ describe('EditGrid Component', () => {
setTimeout(() => {
assert.equal(editGrid.editRows.length, 1);
assert.equal(editGrid.editRows[0].errors?.length, 1);
assert.equal(editGrid.editRows[0].state, 'saving');
assert.equal(editGrid.editRows[0].state, 'new');
done();
}, 300);
}, 300);
Expand Down
42 changes: 42 additions & 0 deletions test/unit/fixtures/editgrid/comp20.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
export default {
title: "edit grid validation",
name: "EG_validation",
path: "EG_validation",
type: "form",
display: "form",
components: [
{
label: 'Root Text',
alwaysEnabled: false,
tableView: true,
key: 'text',
type: 'textfield',
input: true
},
{
label: "Edit Grid",
tableView: false,
validateWhenHidden: false,
rowDrafts: false,
key: "editGrid",
type: "editgrid",
displayAsTable: false,
input: true,
components: [
{
label: 'Textfield - EG',
applyMaskOn: 'change',
tableView: true,
validate: {
custom: "valid = (input === data.text) ? true : 'data must match root textfield';"
},
validateWhenHidden: false,
key: 'rootTest',
type: 'textfield',
alwaysEnabled: false,
input: true
},
],
},
],
};
3 changes: 2 additions & 1 deletion test/unit/fixtures/editgrid/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ import comp16 from './comp16';
import comp17 from './comp17';
import comp18 from './comp18';
import comp19 from './comp19';
import comp20 from './comp20';
import withOpenWhenEmptyAndConditions from './comp-with-conditions-and-openWhenEmpty';
import compOpenWhenEmpty from './comp-openWhenEmpty';
import compWithCustomDefaultValue from './comp-with-custom-default-value';
import compTestEvents from './comp-test-events';
export { comp1, comp2, comp3, comp4, comp5, comp6, comp7, comp8, comp9, comp10, comp11, comp12, comp13, comp14, comp15, comp16, comp17, comp18, comp19, compOpenWhenEmpty, withOpenWhenEmptyAndConditions, compWithCustomDefaultValue, compTestEvents };
export { comp1, comp2, comp3, comp4, comp5, comp6, comp7, comp8, comp9, comp10, comp11, comp12, comp13, comp14, comp15, comp16, comp17, comp18, comp19, comp20, compOpenWhenEmpty, withOpenWhenEmptyAndConditions, compWithCustomDefaultValue, compTestEvents };

0 comments on commit 21c1482

Please sign in to comment.