diff --git a/package.json b/package.json index dd333b3f62..e84c9874d0 100644 --- a/package.json +++ b/package.json @@ -82,7 +82,7 @@ "dependencies": { "@formio/bootstrap": "3.0.0-dev.98.17ba6ea", "@formio/choices.js": "^10.2.1", - "@formio/core": "v2.1.0-dev.174.9a3c6ec", + "@formio/core": "2.1.0-dev.189.e38e07a", "@formio/text-mask-addons": "^3.8.0-formio.3", "@formio/vanilla-text-mask": "^5.1.1-formio.1", "abortcontroller-polyfill": "^1.7.5", diff --git a/src/Webform.js b/src/Webform.js index f53b265983..4c2242ce7d 100644 --- a/src/Webform.js +++ b/src/Webform.js @@ -1519,7 +1519,7 @@ export default class Webform extends NestedDataComponent { }); } - submitForm(options = {}) { + submitForm(options = {}, local = false) { this.clearServerErrors(); return new Promise((resolve, reject) => { @@ -1554,6 +1554,7 @@ export default class Webform extends NestedDataComponent { return reject("Invalid Submission"); } const errors = this.validate(submission.data, { + local, dirty: true, silentCheck: false, process: "submit", @@ -1573,11 +1574,11 @@ export default class Webform extends NestedDataComponent { this.everyComponent((comp) => { if (submission._vnote && comp.type === "form" && comp.component.reference) { - _.get(submission.data, comp.path, {})._vnote = submission._vnote; + _.get(submission.data, local ? comp.paths?.localDataPath : comp.path, {})._vnote = submission._vnote; } const { persistent } = comp.component; if (persistent === "client-only") { - _.unset(submission.data, comp.path); + _.unset(submission.data, local ? comp.paths?.localDataPath : comp.path); } }); diff --git a/src/components/_classes/component/Component.js b/src/components/_classes/component/Component.js index 23058c9614..d451bda131 100644 --- a/src/components/_classes/component/Component.js +++ b/src/components/_classes/component/Component.js @@ -3450,6 +3450,7 @@ export default class Component extends Element { component: this.component, data, row, + local: !!flags.local, value: this.validationValue, parent: this.parent?.component, paths: this.paths, diff --git a/src/components/_classes/nested/NestedComponent.js b/src/components/_classes/nested/NestedComponent.js index a8e155e004..b05c4f680f 100644 --- a/src/components/_classes/nested/NestedComponent.js +++ b/src/components/_classes/nested/NestedComponent.js @@ -786,6 +786,7 @@ export default class NestedComponent extends Field { components, instances: this.componentsMap, data: data, + local: !!flags.local, scope: { errors: [] }, parent: this.component, parentPaths: this.paths, diff --git a/src/components/form/Form.js b/src/components/form/Form.js index a1c3892259..9eb8b552be 100644 --- a/src/components/form/Form.js +++ b/src/components/form/Form.js @@ -596,7 +596,7 @@ export default class FormComponent extends Component { } this.subForm.nosubmit = false; this.subForm.submitted = true; - return this.subForm.submitForm().then(result => { + return this.subForm.submitForm({}, true).then(result => { this.subForm.loading = false; this.subForm.showAllErrors = false; this.dataValue = result.submission; diff --git a/src/utils/conditionOperators/DateGreaterThan.js b/src/utils/conditionOperators/DateGreaterThan.js index 8324ce7025..dca3235296 100644 --- a/src/utils/conditionOperators/DateGreaterThan.js +++ b/src/utils/conditionOperators/DateGreaterThan.js @@ -18,7 +18,7 @@ export default class DateGeaterThan extends ConditionOperator { } execute(options, functionName = 'isAfter') { - const { value, instance, conditionComponentPath } = options; + const { value, instance, path } = options; if (!value) { return false; @@ -27,7 +27,7 @@ export default class DateGeaterThan extends ConditionOperator { let conditionTriggerComponent = null; if (instance?.root?.getComponent) { - conditionTriggerComponent = instance.root.getComponent(conditionComponentPath); + conditionTriggerComponent = instance.root.getComponent(path); } if ( conditionTriggerComponent && conditionTriggerComponent.isPartialDay && conditionTriggerComponent.isPartialDay(value)) { diff --git a/src/utils/conditionOperators/IsEmptyValue.js b/src/utils/conditionOperators/IsEmptyValue.js index 5514771721..40137bede8 100644 --- a/src/utils/conditionOperators/IsEmptyValue.js +++ b/src/utils/conditionOperators/IsEmptyValue.js @@ -14,11 +14,11 @@ export default class IsEmptyValue extends ConditionOperator { return false; } - execute({ value, instance, conditionComponentPath }) { + execute({ value, instance, path }) { const isEmptyValue = _.isEmpty(_.isNumber(value)? String(value): value); if (instance?.root?.getComponent) { - const conditionTriggerComponent = instance.root.getComponent(conditionComponentPath); + const conditionTriggerComponent = instance.root.getComponent(path); return conditionTriggerComponent?.isEmpty ? conditionTriggerComponent.isEmpty() : isEmptyValue; } diff --git a/src/utils/conditionOperators/IsEqualTo.js b/src/utils/conditionOperators/IsEqualTo.js index 4ee93895a7..59ac42144c 100644 --- a/src/utils/conditionOperators/IsEqualTo.js +++ b/src/utils/conditionOperators/IsEqualTo.js @@ -11,7 +11,7 @@ export default class IsEqualTo extends ConditionOperator { return 'Is Equal To'; } - execute({ value, comparedValue, instance, conditionComponentPath }) { + execute({ value, comparedValue, instance, path }) { if ((value || value === false) && comparedValue && typeof value !== typeof comparedValue && _.isString(comparedValue)) { try { comparedValue = JSON.parse(comparedValue); @@ -21,7 +21,7 @@ export default class IsEqualTo extends ConditionOperator { } if (instance?.root?.getComponent) { - const conditionTriggerComponent = instance.root.getComponent(conditionComponentPath); + const conditionTriggerComponent = instance.root.getComponent(path); if ( conditionTriggerComponent diff --git a/src/utils/utils.js b/src/utils/utils.js index ad38386a2d..edee77c8ae 100644 --- a/src/utils/utils.js +++ b/src/utils/utils.js @@ -245,13 +245,12 @@ function getConditionalPathsRecursive(conditionPaths, data) { const conditionalPaths = instance?.parent?.type === 'datagrid' || instance?.parent?.type === 'editgrid' ? [] : getConditionalPathsRecursive(splittedConditionPath, data); - if (conditionalPaths.length>0) { + if (conditionalPaths.length > 0) { return conditionalPaths.map((path) => { const value = getComponentActualValue(path, data, row); - const ConditionOperator = ConditionOperators[operator]; return ConditionOperator - ? new ConditionOperator().getResult({ value, comparedValue, instance, component, conditionComponentPath }) + ? new ConditionOperator().getResult({ value, comparedValue, instance, component, path }) : true; }); } @@ -259,7 +258,7 @@ function getConditionalPathsRecursive(conditionPaths, data) { const value = getComponentActualValue(conditionComponentPath, data, row); const СonditionOperator = ConditionOperators[operator]; return СonditionOperator - ? new СonditionOperator().getResult({ value, comparedValue, instance, component, conditionComponentPath }) + ? new СonditionOperator().getResult({ value, comparedValue, instance, component, path: conditionComponentPath }) : true; } }); diff --git a/test/unit/Tags.unit.js b/test/unit/Tags.unit.js index a80c010218..10f362dcc3 100644 --- a/test/unit/Tags.unit.js +++ b/test/unit/Tags.unit.js @@ -143,20 +143,22 @@ describe('Tags Component', function() { const element = document.createElement('div'); Formio.createForm(element, comp6).then(form => { - const tags = form.getComponent('tags'); - // tags.setValue(['1', '2', '3']); - Harness.setTagsValue(['test', 'test1', 'test2'], tags); - tags.choices.input.element.focus(); - setTimeout(() => { - assert.equal(tags.errors.length, 0, 'Tags should be valid while changing'); - tags.choices.input.element.dispatchEvent(new Event('blur')); - + const tags = form.getComponent('tags'); + // tags.setValue(['1', '2', '3']); + Harness.setTagsValue(['test', 'test1', 'test2'], tags); + tags.choices.input.element.focus(); + setTimeout(() => { - assert.equal(tags.errors.length, 1, 'Should set error after Tags component was blurred'); - done(); - }, 500); - }, 350); + assert.equal(tags.errors.length, 0, 'Tags should be valid while changing'); + tags.choices.input.element.dispatchEvent(new Event('blur')); + + setTimeout(() => { + assert.equal(tags.errors.length, 1, 'Should set error after Tags component was blurred'); + done(); + }, 500); + }, 350); + }, 10); }).catch(done); }); }); diff --git a/yarn.lock b/yarn.lock index 2ab2a0c002..0f2e60da74 100644 --- a/yarn.lock +++ b/yarn.lock @@ -381,15 +381,15 @@ fuse.js "^6.6.2" redux "^4.2.0" -"@formio/core@v2.1.0-dev.174.9a3c6ec": - version "2.1.0-dev.174.9a3c6ec" - resolved "https://registry.yarnpkg.com/@formio/core/-/core-2.1.0-dev.174.9a3c6ec.tgz#f223b5ce4f374a9f4e922dada0af7c029320e035" - integrity sha512-QQK04dP0xBFa3vuhiOi+TUP8Zwqlg38qxzHgDmBwSlRO5XqQIObPJpSSnv2VA8H7fBWWiV2g7AErHBxugJW7Rw== +"@formio/core@2.1.0-dev.189.e38e07a": + version "2.1.0-dev.189.e38e07a" + resolved "https://registry.npmjs.org/@formio/core/-/core-2.1.0-dev.189.e38e07a.tgz#6206322a8a644704651eaa03732f3b93aa2139ac" + integrity sha512-TXa3xTYdaYKWNvc1WzummmNqekFrGhiJmXFecJAqQhmT1SG0dgELE2lH99jHN6AAj5+8VL0TKFKYtqgUy48kHQ== dependencies: browser-cookies "^1.2.0" core-js "^3.38.0" dayjs "^1.11.12" - dompurify "^3.1.6" + dompurify "^3.1.7" eventemitter3 "^5.0.0" fast-json-patch "^3.1.1" fetch-ponyfill "^7.1.0" @@ -2498,6 +2498,11 @@ dompurify@^3.1.6: resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-3.1.6.tgz#43c714a94c6a7b8801850f82e756685300a027e2" integrity sha512-cTOAhc36AalkjtBpfG6O8JimdTMWNXjiePT2xQH/ppBGi/4uIpmj8eKyIkMJErXWARyINV/sB38yf8JCLF5pbQ== +dompurify@^3.1.7: + version "3.2.0" + resolved "https://registry.npmjs.org/dompurify/-/dompurify-3.2.0.tgz#53c414317c51503183696fcdef6dd3f916c607ed" + integrity sha512-AMdOzK44oFWqHEi0wpOqix/fUNY707OmoeFDnbi3Q5I8uOpy21ufUA5cDJPr0bosxrflOVD/H2DMSvuGKJGfmQ== + downloadjs@^1.4.7: version "1.4.7" resolved "https://registry.npmjs.org/downloadjs/-/downloadjs-1.4.7.tgz#f69f96f940e0d0553dac291139865a3cd0101e3c"