diff --git a/src/components/datagrid/DataGrid.js b/src/components/datagrid/DataGrid.js index 76b81e31e6..c085cef1c0 100644 --- a/src/components/datagrid/DataGrid.js +++ b/src/components/datagrid/DataGrid.js @@ -489,7 +489,7 @@ export default class DataGridComponent extends NestedArrayComponent { row }); this.checkConditions(); - this.triggerChange(); + this.triggerChange({ modified: true }); this.redraw().then(() => { this.focusOnNewRowElement(this.rows[index]); }); @@ -577,6 +577,9 @@ export default class DataGridComponent extends NestedArrayComponent { options.name += `[${rowIndex}]`; options.row = `${rowIndex}-${colIndex}`; options.rowIndex = rowIndex; + options.onChange = (flags, changed, modified) => { + this.triggerChange({ modified }); + } let columnComponent; diff --git a/src/components/form/Form.js b/src/components/form/Form.js index c682fcf69e..48d2337aa6 100644 --- a/src/components/form/Form.js +++ b/src/components/form/Form.js @@ -373,6 +373,10 @@ export default class FormComponent extends Component { && this.formObj._vid !== this.subFormRevision; } + get subFormData() { + return this.dataValue?.data || {}; + } + destroy(all = false) { if (this.subForm) { this.subForm.destroy(all); @@ -537,14 +541,14 @@ export default class FormComponent extends Component { } if (this.subForm) { - return this.subForm.checkConditions(data, flags, row); + return this.subForm.checkConditions(this.subFormData, flags); } // There are few cases when subForm is not loaded when a change is triggered, // so we need to perform checkConditions after it is ready, or some conditional fields might be hidden in View mode else if (this.subFormReady) { this.subFormReady.then(() => { if (this.subForm) { - return this.subForm.checkConditions(data, flags, row); + return this.subForm.checkConditions(this.subFormData, flags); } }); } @@ -554,7 +558,7 @@ export default class FormComponent extends Component { calculateValue(data, flags, row) { if (this.subForm) { - return this.subForm.calculateValue(data, flags, row); + return this.subForm.calculateValue(this.subFormData, flags); } return super.calculateValue(data, flags, row); diff --git a/test/unit/DataGrid.unit.js b/test/unit/DataGrid.unit.js index b1287c2a76..a4cd167122 100644 --- a/test/unit/DataGrid.unit.js +++ b/test/unit/DataGrid.unit.js @@ -436,7 +436,7 @@ describe('DataGrid Component', () => { done(); }).catch(done); }, 300); - }, 300); + }, 350); }, 300); }, 300); }) @@ -525,6 +525,93 @@ describe('DataGrid Component', () => { }, 300); }).catch((err) => done(err)); }); + + it('Should trigger DataGrid change event when row component value changes', (done) => { + Formio.createForm(document.createElement('div'), { + type: 'form', + display: 'form', + components: [{ + label: 'Datagrid', + key: 'dataGrid', + type: 'datagrid', + defaultValue: [{ }], + input: true, + components: [ + { + label: 'Number', + key: 'number', + type: 'number', + input: true + }, + ], + }], + }).then((form) => { + form.on('change', ({ changed }) => { + assert(changed.component.key, 'dataGrid'); + done(); + }); + const numberComp = form.getComponent(['dataGrid', 0, 'number']); + numberComp.setValue(1); + }).catch((err) => done(err)); + }); + + it('Should trigger DataGrid change event when adding a new row', (done) => { + Formio.createForm(document.createElement('div'), { + type: 'form', + display: 'form', + components: [{ + label: 'Datagrid', + key: 'dataGrid', + type: 'datagrid', + defaultValue: [{ }], + input: true, + components: [ + { + label: 'Number', + key: 'number', + type: 'number', + input: true + }, + ], + }], + }).then((form) => { + form.on('change', ({ changed }) => { + assert(changed.component.key, 'dataGrid'); + done(); + }); + const dataGrid = form.getComponent(['dataGrid']); + dataGrid.addRow(); + }).catch((err) => done(err)); + }); + + it('Should trigger DataGrid change event when removing the row', (done) => { + Formio.createForm(document.createElement('div'), { + type: 'form', + display: 'form', + components: [{ + label: 'Datagrid', + key: 'dataGrid', + type: 'datagrid', + defaultValue: [{ }], + input: true, + components: [ + { + label: 'Number', + key: 'number', + type: 'number', + input: true + }, + ], + }], + }).then((form) => { + form.on('change', ({ changed }) => { + assert(changed.component.key, 'dataGrid'); + done(); + }); + const dataGrid = form.getComponent(['dataGrid']); + dataGrid.removeRow(0); + }).catch((err) => done(err)); + }); }); describe('DataGrid Panels', () => { @@ -971,7 +1058,7 @@ describe('SaveDraft functionality', () => { { saveDraft: true, skipDraftRestore: true, - saveDraftThrottle: 100 + saveDraftThrottle: 300 } ).then((form) => { setTimeout(() => { diff --git a/test/unit/Webform.unit.js b/test/unit/Webform.unit.js index 7d51605d1f..f446ce47da 100644 --- a/test/unit/Webform.unit.js +++ b/test/unit/Webform.unit.js @@ -217,9 +217,9 @@ describe('Webform tests', function() { assert.equal(textArea.visible, true); assert.equal(textField.visible, true); done(); - }, 300); - }, 300); - }, 300); + }, 400); + }, 400); + }, 400); }); }); @@ -900,7 +900,7 @@ describe('Webform tests', function() { done(); }, 300); }, 300); - }, 300); + }, 450); }).catch((err) => done(err)); }); @@ -3805,7 +3805,7 @@ describe('Webform tests', function() { assert.equal(radio.dataValue, calculatedValues.radio); document.body.innerHTML = ''; done(); - }, 300); + }, 350); }, 300); }, 300); }, 300);