From e5209054e62f31c39bd2dd89beb423f8cba17dd3 Mon Sep 17 00:00:00 2001 From: Travis Tidwell Date: Tue, 30 Jan 2024 11:11:10 -0600 Subject: [PATCH 1/6] Changing interface for unique validations and changing to use processors.submission for the submission processors. --- package.json | 6 ++++-- src/process/process.ts | 2 +- .../validation/rules/validateUnique.ts | 19 ++++++++++++++----- src/types/BaseComponent.ts | 1 + 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 61490056..f6a9ab7f 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,8 @@ "./sdk": "./lib/sdk/index.js", "./model": "./lib/model/index.js", "./process": "./lib/process/index.js", - "./template": "./lib/template/index.js" + "./template": "./lib/template/index.js", + "./types": "./lib/types/index.js" }, "scripts": { "test": "TEST=1 mocha -r ts-node/register -r tsconfig-paths/register -r mock-local-storage -r jsdom-global/register -b -t 0 'src/**/__tests__/*.test.ts'", @@ -41,7 +42,8 @@ }, "files": [ "dist", - "lib" + "lib", + "types.js" ], "homepage": "https://github.com/formio/core#readme", "devDependencies": { diff --git a/src/process/process.ts b/src/process/process.ts index 574de2a7..64409a36 100644 --- a/src/process/process.ts +++ b/src/process/process.ts @@ -83,7 +83,7 @@ export const ProcessorMap: Record> = { }; export const ProcessTargets: ProcessTarget = { - server: [ + submission: [ filterProcessInfo, serverDefaultValueProcessInfo, fetchProcessInfo, diff --git a/src/process/validation/rules/validateUnique.ts b/src/process/validation/rules/validateUnique.ts index 41888154..bedb0fbf 100644 --- a/src/process/validation/rules/validateUnique.ts +++ b/src/process/validation/rules/validateUnique.ts @@ -17,7 +17,7 @@ export const shouldValidate = (context: ValidationContext) => { }; export const validateUnique: RuleFn = async (context: ValidationContext) => { - const { value, config } = context; + const { value, config, component } = context; if (!shouldValidate(context)) { return null; } @@ -25,10 +25,19 @@ export const validateUnique: RuleFn = async (context: ValidationContext) => { if (!config || !config.database) { throw new ValidatorError("Can't test for unique value without a database config object"); } - const isUnique = await config.database?.isUnique(context, value); - return isUnique - ? null - : new FieldError('unique', context); + try { + const isUnique = await config.database?.isUnique(context, value); + if (typeof isUnique === 'string') { + return new FieldError('unique', { + ...context, + component: {...component, conflictId: isUnique}, + }); + } + return (isUnique === true) ? null : new FieldError('unique', context); + } + catch (err: any) { + throw new ValidatorError(err.message || err); + } }; export const validateUniqueInfo: ProcessorInfo = { diff --git a/src/types/BaseComponent.ts b/src/types/BaseComponent.ts index 524591c6..409017e3 100644 --- a/src/types/BaseComponent.ts +++ b/src/types/BaseComponent.ts @@ -79,6 +79,7 @@ export type BaseComponent = { allowMultipleMasks?: boolean; addons?: any[]; // TODO: this should go away inputType?: string; + conflictId?: string; errors?: Record; truncateMultipleSpaces?: boolean; }; From c5e5b4e5c0acecec35e8764a7ea9ea047b9da55d Mon Sep 17 00:00:00 2001 From: Travis Tidwell Date: Tue, 30 Jan 2024 11:11:19 -0600 Subject: [PATCH 2/6] Adding types files. --- types.d.ts | 1 + types.js | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 types.d.ts create mode 100644 types.js diff --git a/types.d.ts b/types.d.ts new file mode 100644 index 00000000..3fa8628d --- /dev/null +++ b/types.d.ts @@ -0,0 +1 @@ +export * from './lib/types'; \ No newline at end of file diff --git a/types.js b/types.js new file mode 100644 index 00000000..e2c85f93 --- /dev/null +++ b/types.js @@ -0,0 +1,17 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +__exportStar(require("./lib/types"), exports); \ No newline at end of file From 2255869b03118ec906f282b04ea6c48ae149722a Mon Sep 17 00:00:00 2001 From: Travis Tidwell Date: Tue, 30 Jan 2024 11:21:00 -0600 Subject: [PATCH 3/6] Revert "Removing unwanted code changes to the adding-processors branch." This reverts commit 534e2228c0cb1c73e0a22d6df52739f9df176024. --- src/index.ts | 1 + src/process/calculation/index.ts | 3 ++- src/process/conditions/index.ts | 1 + src/process/defaultValue/index.ts | 6 +++++- 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/index.ts b/src/index.ts index 90efabc1..38daa95d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,3 +7,4 @@ export * from './components'; export * from './process/validation'; export * from './process'; export * from './template'; +export * from './types/process'; diff --git a/src/process/calculation/index.ts b/src/process/calculation/index.ts index 26c136f5..8d9d6e7e 100644 --- a/src/process/calculation/index.ts +++ b/src/process/calculation/index.ts @@ -1,5 +1,5 @@ import JSONLogic from 'modules/jsonlogic'; -import { ProcessorFn, ProcessorFnSync, CalculationScope, CalculationContext, ProcessorInfo } from 'types'; +import { ProcessorFn, ProcessorFnSync, CalculationScope, CalculationContext, ProcessorInfo, FilterScope } from 'types'; import _set from 'lodash/set'; const Evaluator = JSONLogic.evaluator; @@ -25,6 +25,7 @@ export const calculateProcessSync: ProcessorFnSync = (context: value: newValue }); _set(row, component.key, newValue); + context.value = newValue; return; }; diff --git a/src/process/conditions/index.ts b/src/process/conditions/index.ts index 3654383f..a9734f4b 100644 --- a/src/process/conditions/index.ts +++ b/src/process/conditions/index.ts @@ -116,6 +116,7 @@ export const conditionalProcess = (context: ConditionsContext, isHidden: Conditi scope.conditionals.push({ path, conditionallyHidden: true }); if (!component.hasOwnProperty('clearOnHide') || component.clearOnHide) { unset(row, component.key); + context.value = undefined; } } } diff --git a/src/process/defaultValue/index.ts b/src/process/defaultValue/index.ts index fac7ba93..3b0cbf60 100644 --- a/src/process/defaultValue/index.ts +++ b/src/process/defaultValue/index.ts @@ -1,5 +1,5 @@ import JSONLogic from 'modules/jsonlogic'; -import { ProcessorFn, ProcessorFnSync, ConditionsScope, ProcessorInfo, DefaultValueContext } from 'types'; +import { ProcessorFn, ProcessorFnSync, ConditionsScope, ProcessorInfo, DefaultValueContext, FilterScope } from 'types'; import has from 'lodash/has'; import set from 'lodash/set'; const Evaluator = JSONLogic.evaluator; @@ -84,6 +84,10 @@ export const serverDefaultValueProcessSync: ProcessorFnSync = ( } if (defaultValue !== null && defaultValue !== undefined) { set(row, component.key, defaultValue); + if ((scope as FilterScope).filter) { + set((scope as FilterScope).filter, path, defaultValue); + } + context.value = defaultValue; } }; From e76e9cc2ab22c7496d5f79134a4c81ca6f7804fe Mon Sep 17 00:00:00 2001 From: Travis Tidwell Date: Wed, 31 Jan 2024 14:26:29 -0600 Subject: [PATCH 4/6] Fixing each component to make parent non enumerable. --- src/index.ts | 1 - src/utils/formUtil.ts | 6 +++++- src/utils/index.ts | 1 + 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/index.ts b/src/index.ts index 38daa95d..90efabc1 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,4 +7,3 @@ export * from './components'; export * from './process/validation'; export * from './process'; export * from './template'; -export * from './types/process'; diff --git a/src/utils/formUtil.ts b/src/utils/formUtil.ts index 3d339c69..035589e6 100644 --- a/src/utils/formUtil.ts +++ b/src/utils/formUtil.ts @@ -329,7 +329,11 @@ export function eachComponent( // Keep track of parent references. if (parent) { // Ensure we don't create infinite JSON structures. - component.parent = { ...parent }; + Object.defineProperty(component, 'parent', { + enumerable: false, + writable: true, + value: { ...parent } + }); delete component.parent.components; delete component.parent.componentMap; delete component.parent.columns; diff --git a/src/utils/index.ts b/src/utils/index.ts index e8a718a1..f7ef4494 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -7,4 +7,5 @@ export * as dom from './dom'; export * from './utils'; export * from './date'; export * from './mask'; +export * from './fastCloneDeep'; export * from './Database'; From c71c28c832ca4034000fc625d96c36a329ef5bbb Mon Sep 17 00:00:00 2001 From: Travis Tidwell Date: Mon, 5 Feb 2024 12:56:55 -0600 Subject: [PATCH 5/6] Updated build with fixes to calculation processor. --- package.json | 7 +++-- src/process/calculation/index.ts | 27 ++++++++++++-------- src/process/validation/rules/validateMask.ts | 18 +++++++++---- yarn.lock | 10 ++++++++ 4 files changed, 45 insertions(+), 17 deletions(-) diff --git a/package.json b/package.json index 11c7b4bf..7b36218f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@formio/core", - "version": "2.0.0-rc.9", + "version": "2.0.0-dev.3", "description": "The core Form.io renderering framework.", "main": "lib/index.js", "exports": { @@ -43,7 +43,8 @@ "files": [ "dist", "lib", - "types.js" + "types.js", + "types.d.ts" ], "homepage": "https://github.com/formio/core#readme", "devDependencies": { @@ -52,6 +53,7 @@ "@types/dompurify": "^3.0.5", "@types/fetch-mock": "^7.3.8", "@types/flatpickr": "^3.1.2", + "@types/inputmask": "^5.0.7", "@types/lodash": "^4.14.201", "@types/lodash.template": "^4.5.3", "@types/mocha": "^10.0.4", @@ -90,6 +92,7 @@ "dompurify": "^3.0.6", "eventemitter3": "^5.0.0", "fetch-ponyfill": "^7.1.0", + "inputmask": "^5.0.9-beta.45", "json-logic-js": "^2.0.2", "lodash": "^4.17.21", "moment": "^2.29.4" diff --git a/src/process/calculation/index.ts b/src/process/calculation/index.ts index 8d9d6e7e..1684f7a0 100644 --- a/src/process/calculation/index.ts +++ b/src/process/calculation/index.ts @@ -4,28 +4,35 @@ import _set from 'lodash/set'; const Evaluator = JSONLogic.evaluator; export const shouldCalculate = (context: CalculationContext): boolean => { - const { component } = context; - if (!component.calculateValue || (component.hasOwnProperty('calculateServer') && !component.calculateServer)) { + const { component, config } = context; + if ( + !component.calculateValue || + (config?.server && !component.calculateServer) + ) { return false; } return true; }; export const calculateProcessSync: ProcessorFnSync = (context: CalculationContext) => { - const { component, row, evalContext, scope, path } = context; + const { component, row, evalContext, scope, path, value } = context; if (!shouldCalculate(context)) { return; } const evalContextValue = evalContext ? evalContext(context) : context; evalContextValue.value = null; if (!scope.calculated) scope.calculated = []; - const newValue = Evaluator.evaluate(component.calculateValue, evalContextValue, 'value'); - scope.calculated.push({ - path, - value: newValue - }); - _set(row, component.key, newValue); - context.value = newValue; + let newValue = Evaluator.evaluate(component.calculateValue, evalContextValue, 'value'); + + // Only set a new value if it is not "null" which would be the case if no calculation occurred. + if (newValue !== null) { + scope.calculated.push({ + path, + value: newValue + }); + _set(row, component.key, newValue); + context.value = newValue; + } return; }; diff --git a/src/process/validation/rules/validateMask.ts b/src/process/validation/rules/validateMask.ts index e04255ee..6ee92d36 100644 --- a/src/process/validation/rules/validateMask.ts +++ b/src/process/validation/rules/validateMask.ts @@ -3,6 +3,7 @@ import _, { isEmpty } from 'lodash'; import { FieldError } from 'error'; import { TextFieldComponent, DataObject, RuleFn, RuleFnSync, ValidationContext } from 'types'; import { ProcessorInfo } from 'types/process/ProcessorInfo'; +import Inputmask from 'inputmask'; const isMaskType = (obj: any): obj is DataObject & { maskName: string; value: string } => { return ( @@ -119,21 +120,28 @@ export const validateMaskSync: RuleFnSync = (context: ValidationContext) => { if (!shouldValidate(context)) { return null; } - let inputMask: (string | RegExp)[] | undefined; + let inputMask: string | string[] | undefined; let maskValue: string | undefined; if (component.allowMultipleMasks && (component as TextFieldComponent).inputMasks?.length) { const mask = value && isMaskType(value) ? value : undefined; const formioInputMask = getMaskByLabel(component as TextFieldComponent, mask?.maskName); if (formioInputMask) { - inputMask = getInputMask(formioInputMask); + inputMask = formioInputMask; } maskValue = mask?.value; } else { - inputMask = getInputMask((component as TextFieldComponent).inputMask || ''); + inputMask = (component as TextFieldComponent).inputMask || ''; } - if (value != null && inputMask) { + if (!inputMask) { + return null; + } + if (value && inputMask && typeof value === 'string' && component.type === 'textfield' ) { + return Inputmask.isValid(value, {mask: inputMask.toString()}) ? null : new FieldError('mask', context); + } + let inputMaskArr = getInputMask(inputMask); + if (value != null && inputMaskArr) { const error = new FieldError('mask', context); - return matchInputMask(maskValue || value, inputMask) ? null : error; + return matchInputMask(maskValue || value, inputMaskArr) ? null : error; } return null; }; diff --git a/yarn.lock b/yarn.lock index 50f4f0c3..7e756de3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -438,6 +438,11 @@ dependencies: flatpickr "*" +"@types/inputmask@^5.0.7": + version "5.0.7" + resolved "https://registry.npmjs.org/@types/inputmask/-/inputmask-5.0.7.tgz#ae1afdbb0a7b825b90703e0b08b4ef5be7d2c34e" + integrity sha512-uojbVPWzBQ/n/0jc/d16fLqmGasFIptbrLD2WrCPWArlk+5PgblOqH4EDkI3AoobXLAlOK5yF01V8jMmvMG5qg== + "@types/json-logic-js@^2.0.5": version "2.0.6" resolved "https://registry.npmjs.org/@types/json-logic-js/-/json-logic-js-2.0.6.tgz#ceb090bcaf7ec4d5c7c4c3b5225cf53733e76624" @@ -2666,6 +2671,11 @@ ini@^1.3.4: resolved "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz" integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== +inputmask@^5.0.9-beta.45: + version "5.0.9-beta.45" + resolved "https://registry.npmjs.org/inputmask/-/inputmask-5.0.9-beta.45.tgz#2699ebfd1e99f572815fb8f2ac23c548198f9ec6" + integrity sha512-Nh6RHifykvEfPvnpCiwEER8LcDTAWvWKWUnVsRjqOyutGwAdjFuucCDI3YAm8tTVmhsmAydqEs+ORwllkN7Pfw== + interpret@^1.4.0: version "1.4.0" resolved "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz" From 0974c1a76e926fd26523e9970897c232b6d6dc67 Mon Sep 17 00:00:00 2001 From: Travis Tidwell Date: Wed, 7 Feb 2024 10:00:24 -0600 Subject: [PATCH 6/6] Fixing issues with the component key for non standard fields. --- src/process/calculation/index.ts | 3 ++- src/process/conditions/index.ts | 6 ++--- src/process/defaultValue/index.ts | 12 +++++----- src/process/fetch/index.ts | 6 +++-- src/process/processOne.ts | 12 +++------- src/utils/formUtil.ts | 37 ++++++++++++++++++------------- src/utils/logic.ts | 7 +++--- 7 files changed, 42 insertions(+), 41 deletions(-) diff --git a/src/process/calculation/index.ts b/src/process/calculation/index.ts index 1684f7a0..428ac2e8 100644 --- a/src/process/calculation/index.ts +++ b/src/process/calculation/index.ts @@ -1,6 +1,7 @@ import JSONLogic from 'modules/jsonlogic'; import { ProcessorFn, ProcessorFnSync, CalculationScope, CalculationContext, ProcessorInfo, FilterScope } from 'types'; import _set from 'lodash/set'; +import { getComponentKey } from 'utils/formUtil'; const Evaluator = JSONLogic.evaluator; export const shouldCalculate = (context: CalculationContext): boolean => { @@ -30,7 +31,7 @@ export const calculateProcessSync: ProcessorFnSync = (context: path, value: newValue }); - _set(row, component.key, newValue); + _set(row, getComponentKey(component), newValue); context.value = newValue; } return; diff --git a/src/process/conditions/index.ts b/src/process/conditions/index.ts index a9734f4b..5eebcfb2 100644 --- a/src/process/conditions/index.ts +++ b/src/process/conditions/index.ts @@ -1,7 +1,7 @@ import { ProcessorFn, ProcessorFnSync, ConditionsScope, ProcessorInfo, ConditionsContext, SimpleConditional, JSONConditional, LegacyConditional, SimpleConditionalConditions, Component, NestedComponent, FilterScope } from 'types'; import { Utils } from 'utils'; import unset from 'lodash/unset'; -import { componentInfo, getComponentPath } from 'utils/formUtil'; +import { componentInfo, getComponentKey, getComponentPath } from 'utils/formUtil'; import { checkCustomConditional, checkJsonConditional, @@ -108,14 +108,14 @@ export const conditionalProcess = (context: ConditionsContext, isHidden: Conditi Utils.eachComponentData([component], row, (comp: Component, data: any, compRow: any, compPath: string) => { scope.conditionals?.push({ path: getComponentPath(comp, compPath), conditionallyHidden: true }); if (!comp.hasOwnProperty('clearOnHide') || comp.clearOnHide) { - unset(compRow, comp.key); + unset(compRow, getComponentKey(comp)); } }); } else { scope.conditionals.push({ path, conditionallyHidden: true }); if (!component.hasOwnProperty('clearOnHide') || component.clearOnHide) { - unset(row, component.key); + unset(row, getComponentKey(component)); context.value = undefined; } } diff --git a/src/process/defaultValue/index.ts b/src/process/defaultValue/index.ts index 3b0cbf60..8883f3a3 100644 --- a/src/process/defaultValue/index.ts +++ b/src/process/defaultValue/index.ts @@ -2,6 +2,7 @@ import JSONLogic from 'modules/jsonlogic'; import { ProcessorFn, ProcessorFnSync, ConditionsScope, ProcessorInfo, DefaultValueContext, FilterScope } from 'types'; import has from 'lodash/has'; import set from 'lodash/set'; +import { getComponentKey } from 'utils/formUtil'; const Evaluator = JSONLogic.evaluator; export const hasCustomDefaultValue = (context: DefaultValueContext): boolean => { @@ -34,7 +35,7 @@ export const customDefaultValueProcessSync: ProcessorFnSync = ( return; } if (!scope.defaultValues) scope.defaultValues = []; - if (has(row, component.key)) { + if (has(row, getComponentKey(component))) { return; } let defaultValue = null; @@ -51,7 +52,7 @@ export const customDefaultValueProcessSync: ProcessorFnSync = ( }); } if (defaultValue !== null && defaultValue !== undefined) { - set(row, component.key, defaultValue); + set(row, getComponentKey(component), defaultValue); } }; @@ -65,7 +66,7 @@ export const serverDefaultValueProcessSync: ProcessorFnSync = ( return; } if (!scope.defaultValues) scope.defaultValues = []; - if (has(row, component.key)) { + if (has(row, getComponentKey(component))) { return; } let defaultValue = null; @@ -83,10 +84,7 @@ export const serverDefaultValueProcessSync: ProcessorFnSync = ( }); } if (defaultValue !== null && defaultValue !== undefined) { - set(row, component.key, defaultValue); - if ((scope as FilterScope).filter) { - set((scope as FilterScope).filter, path, defaultValue); - } + set(row, getComponentKey(component), defaultValue); context.value = defaultValue; } }; diff --git a/src/process/fetch/index.ts b/src/process/fetch/index.ts index ab96cb91..dfe9aafe 100644 --- a/src/process/fetch/index.ts +++ b/src/process/fetch/index.ts @@ -2,6 +2,7 @@ import { ProcessorFn, ProcessorInfo, FetchContext, FetchScope, FetchFn } from 't import get from 'lodash/get'; import set from 'lodash/set'; import { Evaluator } from 'utils'; +import { getComponentKey } from 'utils/formUtil'; export const shouldFetch = (context: FetchContext): boolean => { const { component } = context; @@ -64,13 +65,14 @@ export const fetchProcess: ProcessorFn = async (context: FetchContex const mapFunction = get(component, 'fetch.mapFunction'); // Set the row data of the fetched value. - set(row, component.key, mapFunction ? Evaluator.evaluate(mapFunction, { + const key = getComponentKey(component); + set(row, key, mapFunction ? Evaluator.evaluate(mapFunction, { ...evalContextValue, ...{responseData: result} }, 'value') : result); scope.fetched.push({ path, - value: get(row, component.key) + value: get(row, key) }); } catch (err: any) { diff --git a/src/process/processOne.ts b/src/process/processOne.ts index 7f0b0220..b5011a6a 100644 --- a/src/process/processOne.ts +++ b/src/process/processOne.ts @@ -1,15 +1,9 @@ import { get } from "lodash"; -import { CheckboxComponent, Component, ProcessorsContext, ProcessorType } from "types"; +import { Component, ProcessorsContext, ProcessorType } from "types"; +import { getComponentKey } from "utils/formUtil"; export function dataValue(component: Component, row: any) { - let key = component.key; - if ( - component.type === 'checkbox' && - component.inputType === 'radio' && - (component as CheckboxComponent).name - ) { - key = (component as CheckboxComponent).name; - } + const key = getComponentKey(component); return key ? get(row, key) : undefined; } diff --git a/src/utils/formUtil.ts b/src/utils/formUtil.ts index 035589e6..595e7cae 100644 --- a/src/utils/formUtil.ts +++ b/src/utils/formUtil.ts @@ -2,6 +2,7 @@ import { last, get, isEmpty, isNil, isObject } from "lodash"; import { AsyncComponentDataCallback, + CheckboxComponent, Component, ComponentDataCallback, DataObject, @@ -114,23 +115,24 @@ export function getModelType(component: any) { if ((component.input === false) || isComponentModelType(component, 'layout')) { return 'inherit'; } - if (component.key) { + if (getComponentKey(component)) { return 'value'; } return 'inherit'; } export function getComponentPath(component: Component, path: string) { - if (!component.key) { + const key = getComponentKey(component); + if (!key) { return path; } if (!path) { - return component.key; + return key; } - if (path.match(new RegExp(`${component.key}$`))) { + if (path.match(new RegExp(`${key}$`))) { return path; } - return (getModelType(component) === 'inherit') ? `${path}.${component.key}` : path; + return (getModelType(component) === 'inherit') ? `${path}.${key}` : path; } export function isComponentModelType(component: any, modelType: string) { @@ -146,7 +148,8 @@ export function isComponentNestedDataType(component: any) { export function componentPath(component: any, parentPath?: string) { parentPath = component.parentPath || parentPath; - if (!component.key) { + const key = getComponentKey(component); + if (!key) { // If the component does not have a key, then just always return the parent path. return parentPath; } @@ -155,15 +158,6 @@ export function componentPath(component: any, parentPath?: string) { if (component.path) { return component.path; } - - let key = component.key; - if ( - component.type === 'checkbox' && - component.inputType === 'radio' && - component.name - ) { - key = component.name; - } return parentPath ? `${parentPath}.${key}` : key; } @@ -274,8 +268,19 @@ export const eachComponentData = ( ); }; +export function getComponentKey(component: Component) { + if ( + component.type === 'checkbox' && + component.inputType === 'radio' && + (component as CheckboxComponent).name + ) { + return (component as CheckboxComponent).name; + } + return component.key; +} + export function getContextualRowPath(component: Component, path: string): string { - return path.replace(new RegExp(`\.?${component.key}$`), ''); + return path.replace(new RegExp(`\.?${getComponentKey(component)}$`), ''); } diff --git a/src/utils/logic.ts b/src/utils/logic.ts index 17ffb87a..cf4c73e8 100644 --- a/src/utils/logic.ts +++ b/src/utils/logic.ts @@ -3,6 +3,7 @@ import { checkCustomConditional, checkJsonConditional, checkLegacyConditional, c import { LogicActionCustomAction, LogicActionMergeComponentSchema, LogicActionProperty, LogicActionPropertyBoolean, LogicActionPropertyString, LogicActionValue } from "types/AdvancedLogic"; import { get, set, clone, isEqual, assign } from 'lodash'; import { evaluate, interpolate } from 'modules/jsonlogic'; +import { getComponentKey } from "./formUtil"; export const hasLogic = (context: LogicContext): boolean => { const { component } = context; @@ -79,7 +80,7 @@ export function setActionProperty(context: LogicContext, action: LogicActionProp export function setValueProperty(context: LogicContext, action: LogicActionValue) { const { component, row, value } = context; - const oldValue = get(row, component.key); + const oldValue = get(row, getComponentKey(component)); const newValue = evaluate({...context, value}, action.value, 'value', (evalContext: any) => { evalContext.value = clone(oldValue); }); @@ -88,7 +89,7 @@ export function setValueProperty(context: LogicContext, action: LogicActionValue !(component.clearOnHide && conditionallyHidden(context as ProcessorContext)) ) { context.value = newValue; - set(row, component.key, newValue); + set(row, getComponentKey(component), newValue); return true; } return false; @@ -96,7 +97,7 @@ export function setValueProperty(context: LogicContext, action: LogicActionValue export function setMergeComponentSchema(context: LogicContext, action: LogicActionMergeComponentSchema) { const { component, row } = context; - const oldValue = get(row, component.key); + const oldValue = get(row, getComponentKey(component)); const schema = evaluate({...context, value: {}}, action.schemaDefinition, 'schema', (evalContext: any) => { evalContext.value = clone(oldValue); });