@formio/js 5.0.0-rc.99 → 5.1.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/dist/formio.embed.js +1 -1
  2. package/dist/formio.embed.min.js +1 -1
  3. package/dist/formio.embed.min.js.LICENSE.txt +1 -1
  4. package/dist/formio.form.js +122 -121
  5. package/dist/formio.form.min.js +1 -1
  6. package/dist/formio.form.min.js.LICENSE.txt +3 -11
  7. package/dist/formio.full.js +123 -122
  8. package/dist/formio.full.min.js +1 -1
  9. package/dist/formio.full.min.js.LICENSE.txt +3 -11
  10. package/dist/formio.js +3011 -281
  11. package/dist/formio.min.js +1 -1
  12. package/dist/formio.min.js.LICENSE.txt +14 -2
  13. package/dist/formio.utils.js +65 -54
  14. package/dist/formio.utils.min.js +1 -1
  15. package/dist/formio.utils.min.js.LICENSE.txt +7 -5
  16. package/lib/cjs/Webform.d.ts +8 -1
  17. package/lib/cjs/Webform.js +40 -32
  18. package/lib/cjs/WebformBuilder.js +22 -18
  19. package/lib/cjs/Wizard.d.ts +0 -1
  20. package/lib/cjs/Wizard.js +19 -33
  21. package/lib/cjs/components/Components.d.ts +0 -7
  22. package/lib/cjs/components/Components.js +1 -33
  23. package/lib/cjs/components/_classes/component/Component.d.ts +37 -7
  24. package/lib/cjs/components/_classes/component/Component.js +70 -26
  25. package/lib/cjs/components/_classes/component/editForm/Component.edit.validation.js +1 -1
  26. package/lib/cjs/components/_classes/componentModal/ComponentModal.d.ts +1 -0
  27. package/lib/cjs/components/_classes/componentModal/ComponentModal.js +1 -0
  28. package/lib/cjs/components/_classes/nested/NestedComponent.d.ts +4 -19
  29. package/lib/cjs/components/_classes/nested/NestedComponent.js +38 -53
  30. package/lib/cjs/components/_classes/nestedarray/NestedArrayComponent.d.ts +2 -1
  31. package/lib/cjs/components/_classes/nestedarray/NestedArrayComponent.js +7 -44
  32. package/lib/cjs/components/datagrid/DataGrid.d.ts +0 -1
  33. package/lib/cjs/components/datagrid/DataGrid.js +1 -45
  34. package/lib/cjs/components/datamap/DataMap.js +1 -2
  35. package/lib/cjs/components/editgrid/EditGrid.js +6 -6
  36. package/lib/cjs/components/form/Form.d.ts +8 -3
  37. package/lib/cjs/components/form/Form.js +26 -25
  38. package/lib/cjs/components/html/HTML.js +1 -1
  39. package/lib/cjs/components/selectboxes/SelectBoxes.js +8 -1
  40. package/lib/cjs/components/signature/Signature.d.ts +0 -1
  41. package/lib/cjs/components/signature/Signature.js +1 -1
  42. package/lib/cjs/utils/conditionOperators/DateGreaterThan.js +2 -2
  43. package/lib/cjs/utils/conditionOperators/IsEmptyValue.d.ts +2 -2
  44. package/lib/cjs/utils/conditionOperators/IsEmptyValue.js +2 -2
  45. package/lib/cjs/utils/conditionOperators/IsEqualTo.d.ts +2 -2
  46. package/lib/cjs/utils/conditionOperators/IsEqualTo.js +2 -2
  47. package/lib/cjs/utils/formUtils.d.ts +25 -14
  48. package/lib/cjs/utils/formUtils.js +11 -16
  49. package/lib/cjs/utils/utils.d.ts +1 -3
  50. package/lib/cjs/utils/utils.js +19 -35
  51. package/lib/mjs/Webform.d.ts +8 -1
  52. package/lib/mjs/Webform.js +37 -31
  53. package/lib/mjs/WebformBuilder.js +22 -18
  54. package/lib/mjs/Wizard.d.ts +0 -1
  55. package/lib/mjs/Wizard.js +16 -29
  56. package/lib/mjs/components/Components.d.ts +0 -7
  57. package/lib/mjs/components/Components.js +1 -32
  58. package/lib/mjs/components/_classes/component/Component.d.ts +37 -7
  59. package/lib/mjs/components/_classes/component/Component.js +80 -27
  60. package/lib/mjs/components/_classes/component/editForm/Component.edit.validation.js +1 -1
  61. package/lib/mjs/components/_classes/componentModal/ComponentModal.d.ts +1 -0
  62. package/lib/mjs/components/_classes/componentModal/ComponentModal.js +1 -0
  63. package/lib/mjs/components/_classes/nested/NestedComponent.d.ts +4 -19
  64. package/lib/mjs/components/_classes/nested/NestedComponent.js +39 -54
  65. package/lib/mjs/components/_classes/nestedarray/NestedArrayComponent.d.ts +2 -1
  66. package/lib/mjs/components/_classes/nestedarray/NestedArrayComponent.js +8 -43
  67. package/lib/mjs/components/datagrid/DataGrid.d.ts +0 -1
  68. package/lib/mjs/components/datagrid/DataGrid.js +1 -45
  69. package/lib/mjs/components/datamap/DataMap.js +1 -2
  70. package/lib/mjs/components/editgrid/EditGrid.js +9 -6
  71. package/lib/mjs/components/form/Form.d.ts +8 -3
  72. package/lib/mjs/components/form/Form.js +27 -25
  73. package/lib/mjs/components/html/HTML.js +1 -1
  74. package/lib/mjs/components/selectboxes/SelectBoxes.js +8 -1
  75. package/lib/mjs/components/signature/Signature.d.ts +0 -1
  76. package/lib/mjs/components/signature/Signature.js +1 -1
  77. package/lib/mjs/utils/conditionOperators/DateGreaterThan.js +2 -2
  78. package/lib/mjs/utils/conditionOperators/IsEmptyValue.d.ts +2 -2
  79. package/lib/mjs/utils/conditionOperators/IsEmptyValue.js +2 -2
  80. package/lib/mjs/utils/conditionOperators/IsEqualTo.d.ts +2 -2
  81. package/lib/mjs/utils/conditionOperators/IsEqualTo.js +2 -2
  82. package/lib/mjs/utils/formUtils.d.ts +25 -14
  83. package/lib/mjs/utils/formUtils.js +2 -12
  84. package/lib/mjs/utils/utils.d.ts +1 -3
  85. package/lib/mjs/utils/utils.js +18 -33
  86. package/package.json +4 -4
@@ -6,7 +6,7 @@ import isMobile from 'ismobilejs';
6
6
  import { processOne, processOneSync, validateProcessInfo } from '@formio/core/process';
7
7
  import { Formio } from '../../../Formio';
8
8
  import * as FormioUtils from '../../../utils/utils';
9
- import { fastCloneDeep, boolValue, getComponentPath, isInsideScopingComponent, currentTimezone, getScriptPlugin } from '../../../utils/utils';
9
+ import { fastCloneDeep, boolValue, isInsideScopingComponent, currentTimezone, getScriptPlugin, getContextualRowData } from '../../../utils/utils';
10
10
  import Element from '../../../Element';
11
11
  import ComponentModal from '../componentModal/ComponentModal';
12
12
  import Widgets from '../../../widgets';
@@ -221,6 +221,10 @@ export default class Component extends Element {
221
221
  * @private
222
222
  */
223
223
  this._hasCondition = null;
224
+ /**
225
+ * The row index for this component.
226
+ */
227
+ this._rowIndex = undefined;
224
228
  /**
225
229
  * References to dom elements
226
230
  */
@@ -231,11 +235,6 @@ export default class Component extends Element {
231
235
  this.options.components[component.type]) {
232
236
  _.merge(component, this.options.components[component.type]);
233
237
  }
234
- /**
235
- * The data path to this specific component instance.
236
- * @type {string}
237
- */
238
- this.path = component?.key || '';
239
238
  /**
240
239
  * An array of all the children components errors.
241
240
  */
@@ -304,6 +303,14 @@ export default class Component extends Element {
304
303
  * @type {Component}
305
304
  */
306
305
  this.parent = this.options.parent;
306
+ /**
307
+ * The component paths for this component.
308
+ * @type {import('@formio/core').ComponentPaths} - The component paths.
309
+ */
310
+ this.paths = FormioUtils.getComponentPaths(this.component, this.parent?.component, {
311
+ ...this.parent?.paths,
312
+ dataIndex: this.options.rowIndex === undefined ? this.parent?.paths?.dataIndex : this.options.rowIndex
313
+ });
307
314
  this.options.name = this.options.name || 'data';
308
315
  this._path = '';
309
316
  // Needs for Nextgen Rules Engine
@@ -409,12 +416,7 @@ export default class Component extends Element {
409
416
  }
410
417
  /* eslint-enable max-statements */
411
418
  get componentsMap() {
412
- if (this.localRoot?.childComponentsMap) {
413
- return this.localRoot.childComponentsMap;
414
- }
415
- const localMap = {};
416
- localMap[this.path] = this;
417
- return localMap;
419
+ return this.root?.childComponentsMap || {};
418
420
  }
419
421
  get data() {
420
422
  return this._data;
@@ -460,6 +462,25 @@ export default class Component extends Element {
460
462
  this.component.addons.forEach((addon) => this.createAddon(addon));
461
463
  }
462
464
  }
465
+ /**
466
+ * Get Row Index.
467
+ * @returns {number} - The row index.
468
+ */
469
+ get rowIndex() {
470
+ return this._rowIndex;
471
+ }
472
+ /**
473
+ * Set Row Index to row and update each component.
474
+ * @param {number} value - The row index.
475
+ * @returns {void}
476
+ */
477
+ set rowIndex(value) {
478
+ this.paths = FormioUtils.getComponentPaths(this.component, this.parent?.component, {
479
+ ...(this.parent?.paths || {}),
480
+ ...{ dataIndex: value }
481
+ });
482
+ this._rowIndex = value;
483
+ }
463
484
  afterComponentAssign() {
464
485
  //implement in extended classes
465
486
  }
@@ -528,6 +549,12 @@ export default class Component extends Element {
528
549
  get key() {
529
550
  return _.get(this.component, 'key', '');
530
551
  }
552
+ get path() {
553
+ return this.paths.dataPath;
554
+ }
555
+ set path(path) {
556
+ throw new Error('Should not be setting the path of a component.');
557
+ }
531
558
  set parentVisible(value) {
532
559
  this._parentVisible = value;
533
560
  }
@@ -1013,6 +1040,14 @@ export default class Component extends Element {
1013
1040
  setOpenModalElement(template = null) {
1014
1041
  this.componentModal.setOpenModalElement(template || this.getModalPreviewTemplate());
1015
1042
  }
1043
+ /**
1044
+ * Renders a modal preview template and returns the markup as a string
1045
+ * @param {object|null|undefined} ctx - The rendering context
1046
+ * @return {string} - The modal preview markup
1047
+ */
1048
+ renderModalPreview(ctx) {
1049
+ return this.renderTemplate('modalPreview', ctx || {});
1050
+ }
1016
1051
  /**
1017
1052
  * Returns the modal preview template.
1018
1053
  * @returns {string} - The modal preview template.
@@ -1023,7 +1058,7 @@ export default class Component extends Element {
1023
1058
  if (this.hasInput && this.component.validate?.required && !this.isPDFReadOnlyMode) {
1024
1059
  modalLabel = { className: 'field-required' };
1025
1060
  }
1026
- return this.renderTemplate('modalPreview', {
1061
+ return this.renderModalPreview({
1027
1062
  previewText: this.getValueAsString(dataValue, { modalPreview: true }) || this.t('Click to set value'),
1028
1063
  messages: '',
1029
1064
  labelInfo: modalLabel,
@@ -1072,6 +1107,27 @@ export default class Component extends Element {
1072
1107
  }, topLevel);
1073
1108
  }
1074
1109
  }
1110
+ /**
1111
+ * Creates the tooltip instance using tippy.js and returns it
1112
+ * @param {HTMLElement} tooltipEl - HTML element to attach the tooltip
1113
+ * @param {object|null|undefined} settings - tippy.js options
1114
+ * @return {import('tippy.js').Tippy} - tippy.js instance
1115
+ */
1116
+ createTooltip(tooltipEl, settings = {}) {
1117
+ const tooltipAttribute = tooltipEl.getAttribute('data-tooltip');
1118
+ const tooltipDataTitle = tooltipEl.getAttribute('data-title');
1119
+ const tooltipText = this.interpolate(tooltipDataTitle || tooltipAttribute)
1120
+ .replace(/(?:\r\n|\r|\n)/g, '<br />');
1121
+ return tippy(tooltipEl, {
1122
+ allowHTML: true,
1123
+ trigger: 'mouseenter click focus',
1124
+ placement: 'right',
1125
+ zIndex: 10000,
1126
+ interactive: true,
1127
+ ...settings,
1128
+ content: this.t(this.sanitize(tooltipText), { _userInput: true }),
1129
+ });
1130
+ }
1075
1131
  /**
1076
1132
  * Attaches all the tooltips provided the refs object.
1077
1133
  * @param {object} toolTipsRefs - The refs for the tooltips within your template.
@@ -1080,18 +1136,7 @@ export default class Component extends Element {
1080
1136
  attachTooltips(toolTipsRefs) {
1081
1137
  toolTipsRefs?.forEach((tooltip, index) => {
1082
1138
  if (tooltip) {
1083
- const tooltipAttribute = tooltip.getAttribute('data-tooltip');
1084
- const tooltipDataTitle = tooltip.getAttribute('data-title');
1085
- const tooltipText = this.interpolate(tooltipDataTitle || tooltipAttribute)
1086
- .replace(/(?:\r\n|\r|\n)/g, '<br />');
1087
- this.tooltips[index] = tippy(tooltip, {
1088
- allowHTML: true,
1089
- trigger: 'mouseenter click focus',
1090
- placement: 'right',
1091
- zIndex: 10000,
1092
- interactive: true,
1093
- content: this.t(this.sanitize(tooltipText), { _userInput: true }),
1094
- });
1139
+ this.tooltips[index] = this.createTooltip(tooltip);
1095
1140
  }
1096
1141
  });
1097
1142
  }
@@ -1228,7 +1273,7 @@ export default class Component extends Element {
1228
1273
  if (refreshData === 'data') {
1229
1274
  this.refresh(this.data, changed, flags);
1230
1275
  }
1231
- else if ((changePath && getComponentPath(changed.instance) === refreshData) && changed && changed.instance &&
1276
+ else if ((changePath && (changed.instance?.paths?.localPath === refreshData)) && changed && changed.instance &&
1232
1277
  // Make sure the changed component is not in a different "context". Solves issues where refreshOn being set
1233
1278
  // in fields inside EditGrids could alter their state from other rows (which is bad).
1234
1279
  this.inContext(changed.instance)) {
@@ -2832,6 +2877,9 @@ export default class Component extends Element {
2832
2877
  * @returns {string} - The message to show when the component is invalid.
2833
2878
  */
2834
2879
  invalidMessage(data, dirty, ignoreCondition, row) {
2880
+ if (!row) {
2881
+ row = getContextualRowData(this.component, data, this.paths);
2882
+ }
2835
2883
  if (!ignoreCondition && !this.checkCondition(row, data)) {
2836
2884
  return '';
2837
2885
  }
@@ -2849,6 +2897,8 @@ export default class Component extends Element {
2849
2897
  data,
2850
2898
  row,
2851
2899
  path: this.path || this.component.key,
2900
+ parent: this.parent?.component,
2901
+ paths: this.paths,
2852
2902
  scope: validationScope,
2853
2903
  instance: this,
2854
2904
  processors: [
@@ -2901,7 +2951,7 @@ export default class Component extends Element {
2901
2951
  if (flags.silentCheck) {
2902
2952
  return [];
2903
2953
  }
2904
- let isDirty = this.dirty || flags.dirty;
2954
+ let isDirty = (flags.dirty === false) ? false : (this.dirty || flags.dirty);
2905
2955
  if (this.options.alwaysDirty) {
2906
2956
  isDirty = true;
2907
2957
  }
@@ -2926,7 +2976,10 @@ export default class Component extends Element {
2926
2976
  component: this.component,
2927
2977
  data,
2928
2978
  row,
2979
+ local: !!flags.local,
2929
2980
  value: this.validationValue,
2981
+ parent: this.parent?.component,
2982
+ paths: this.paths,
2930
2983
  path: this.path || this.component.key,
2931
2984
  instance: this,
2932
2985
  form: this.root ? this.root._form : {},
@@ -22,7 +22,7 @@ export default [
22
22
  weight: 100,
23
23
  type: 'checkbox',
24
24
  label: 'Validate When Hidden',
25
- tooltip: 'Validates the component when it is hidden/conditionally hidden. Vaildation errors are displayed in the error alert on the form submission.',
25
+ tooltip: 'Validates the component when it is hidden/conditionally hidden. Vaildation errors are displayed in the error alert on the form submission. Use caution when enabling this setting, as it can cause a hidden component to be invalid with no way for the form user to correct it.',
26
26
  key: 'validateWhenHidden',
27
27
  input: true
28
28
  },
@@ -22,6 +22,7 @@ export default class ComponentModal {
22
22
  modalOverlay: string;
23
23
  modalContents: string;
24
24
  modalClose: string;
25
+ componentContent: string;
25
26
  openModalWrapper: string;
26
27
  openModal: string;
27
28
  modalSave: string;
@@ -61,6 +61,7 @@ export default class ComponentModal {
61
61
  modalOverlay: 'single',
62
62
  modalContents: 'single',
63
63
  modalClose: 'single',
64
+ componentContent: 'single',
64
65
  openModalWrapper: 'single',
65
66
  openModal: 'single',
66
67
  modalSave: 'single',
@@ -56,18 +56,6 @@ export default class NestedComponent extends Field {
56
56
  * @returns {object} - The current form object.
57
57
  */
58
58
  get currentForm(): object;
59
- /**
60
- * Set Row Index to row and update each component.
61
- * @param {number} value - The row index.
62
- * @returns {void}
63
- */
64
- set rowIndex(value: number);
65
- /**
66
- * Get Row Index.
67
- * @returns {number} - The row index.
68
- */
69
- get rowIndex(): number;
70
- _rowIndex: number | undefined;
71
59
  /**
72
60
  * Get Contextual data of the component.
73
61
  * @returns {object} - The contextual data of the component.
@@ -115,14 +103,11 @@ export default class NestedComponent extends Field {
115
103
  */
116
104
  eachComponent(fn: Function): void;
117
105
  /**
118
- * Returns a component provided a key. This performs a deep search within the
119
- * component tree.
106
+ * Returns a component provided a key. This performs a deep search within the component tree.
120
107
  * @param {string} path - The path to the component.
121
- * @param {Function} [fn] - Called with the component once found.
122
- * @param {string} [originalPath] - The original path to the component.
123
108
  * @returns {any} - The component that is located.
124
109
  */
125
- getComponent(path: string, fn?: Function | undefined, originalPath?: string | undefined): any;
110
+ getComponent(path: string): any;
126
111
  /**
127
112
  * Return a component provided the Id of the component.
128
113
  * @param {string} id - The Id of the component.
@@ -211,12 +196,12 @@ export default class NestedComponent extends Field {
211
196
  calculateValue(data: any, flags: any, row: any): any;
212
197
  isLastPage(): boolean;
213
198
  isValid(data: any, dirty: any): any;
214
- validationProcessor({ scope, data, row, instance, component }: {
199
+ validationProcessor({ scope, data, row, instance, paths }: {
215
200
  scope: any;
216
201
  data: any;
217
202
  row: any;
218
203
  instance: any;
219
- component: any;
204
+ paths: any;
220
205
  }, flags: any): void;
221
206
  /**
222
207
  * Perform a validation on all child components of this nested component.
@@ -2,7 +2,8 @@
2
2
  import _ from 'lodash';
3
3
  import Field from '../field/Field';
4
4
  import Components from '../../Components';
5
- import { getArrayFromComponentPath, getStringFromComponentPath, getRandomComponentId } from '../../../utils/utils';
5
+ '';
6
+ import { getComponentPaths, getRandomComponentId, componentMatches, getBestMatch, getStringFromComponentPath } from '../../../utils/utils';
6
7
  import { process as processAsync, processSync } from '@formio/core/process';
7
8
  /**
8
9
  * NestedComponent class.
@@ -198,6 +199,10 @@ export default class NestedComponent extends Field {
198
199
  */
199
200
  set rowIndex(value) {
200
201
  this._rowIndex = value;
202
+ this.paths = getComponentPaths(this.component, this.parent?.component, {
203
+ ...(this.parent?.paths || {}),
204
+ ...{ dataIndex: value }
205
+ });
201
206
  this.eachComponent((component) => {
202
207
  component.rowIndex = value;
203
208
  });
@@ -293,56 +298,36 @@ export default class NestedComponent extends Field {
293
298
  });
294
299
  }
295
300
  /**
296
- * Returns a component provided a key. This performs a deep search within the
297
- * component tree.
301
+ * Returns a component provided a key. This performs a deep search within the component tree.
298
302
  * @param {string} path - The path to the component.
299
- * @param {Function} [fn] - Called with the component once found.
300
- * @param {string} [originalPath] - The original path to the component.
301
303
  * @returns {any} - The component that is located.
302
304
  */
303
- getComponent(path, fn, originalPath) {
304
- originalPath = originalPath || getStringFromComponentPath(path);
305
- if (this.componentsMap.hasOwnProperty(originalPath)) {
306
- if (fn) {
307
- return fn(this.componentsMap[originalPath]);
308
- }
309
- else {
310
- return this.componentsMap[originalPath];
311
- }
312
- }
313
- path = getArrayFromComponentPath(path);
314
- const pathStr = originalPath;
315
- const newPath = _.clone(path);
316
- let key = newPath.shift();
317
- const remainingPath = newPath;
318
- let comp = null;
319
- let possibleComp = null;
320
- if (_.isNumber(key)) {
321
- key = remainingPath.shift();
322
- }
323
- if (!_.isString(key)) {
324
- return comp;
325
- }
326
- this.everyComponent((component, components) => {
327
- const matchPath = component.hasInput && component.path ? pathStr.includes(component.path) : true;
328
- if (component.component.key === key) {
329
- possibleComp = component;
330
- if (matchPath) {
331
- comp = component;
332
- if (remainingPath.length > 0 && 'getComponent' in component) {
333
- comp = component.getComponent(remainingPath, fn, originalPath);
334
- }
335
- else if (fn) {
336
- fn(component, components);
337
- }
338
- return false;
339
- }
340
- }
305
+ getComponent(path) {
306
+ path = getStringFromComponentPath(path);
307
+ const matches = {
308
+ path: undefined,
309
+ fullPath: undefined,
310
+ localPath: undefined,
311
+ fullLocalPath: undefined,
312
+ dataPath: undefined,
313
+ localDataPath: undefined,
314
+ key: undefined,
315
+ };
316
+ this.everyComponent((component) => {
317
+ // All searches are relative to this component so replace this path from the child paths.
318
+ componentMatches(component.component, {
319
+ path: component.paths?.path?.replace(new RegExp(`^${this.paths?.path}\\.?`), ''),
320
+ fullPath: component.paths?.fullPath?.replace(new RegExp(`^${this.paths?.fullPath}\\.?`), ''),
321
+ localPath: component.paths?.localPath?.replace(new RegExp(`^${this.paths?.localPath}\\.?`), ''),
322
+ fullLocalPath: component.paths?.fullLocalPath?.replace(new RegExp(`^${this.paths?.fullLocalPath}\\.?`), ''),
323
+ dataPath: component.paths?.dataPath?.replace(new RegExp(`^${this.paths?.dataPath}\\.?`), ''),
324
+ localDataPath: component.paths?.localDataPath?.replace(new RegExp(`^${this.paths?.localDataPath}\\.?`), ''),
325
+ }, path, this.rowIndex, matches, (type, match) => {
326
+ match.instance = component;
327
+ return match;
328
+ });
341
329
  });
342
- if (!comp) {
343
- comp = possibleComp;
344
- }
345
- return comp;
330
+ return getBestMatch(matches)?.instance;
346
331
  }
347
332
  /**
348
333
  * Return a component provided the Id of the component.
@@ -678,19 +663,16 @@ export default class NestedComponent extends Field {
678
663
  isValid(data, dirty) {
679
664
  return this.getComponents().reduce((valid, comp) => comp.isValid(data, dirty) && valid, super.isValid(data, dirty));
680
665
  }
681
- validationProcessor({ scope, data, row, instance, component }, flags) {
666
+ validationProcessor({ scope, data, row, instance, paths }, flags) {
682
667
  const { dirty } = flags;
683
668
  if (this.root.hasExtraPages && this.page !== this.root.page) {
684
- instance = this.childComponentsMap?.hasOwnProperty(component.path)
685
- ? this.childComponentsMap[component.path]
686
- : this.getComponent(component.path);
669
+ instance = this.componentsMap?.hasOwnProperty(paths.dataPath)
670
+ ? this.componentsMap[paths.dataPath]
671
+ : this.getComponent(paths.dataPath);
687
672
  }
688
673
  if (!instance) {
689
674
  return;
690
675
  }
691
- if (!instance.component.path) {
692
- instance.component.path = component.path;
693
- }
694
676
  instance.checkComponentValidity(data, dirty, row, flags, scope.errors);
695
677
  if (instance.processOwnValidation) {
696
678
  scope.noRecurse = true;
@@ -722,7 +704,10 @@ export default class NestedComponent extends Field {
722
704
  components,
723
705
  instances: this.componentsMap,
724
706
  data: data,
707
+ local: !!flags.local,
725
708
  scope: { errors: [] },
709
+ parent: this.component,
710
+ parentPaths: this.paths,
726
711
  processors: [
727
712
  {
728
713
  process: validationProcessorProcess,
@@ -2,6 +2,8 @@ export default class NestedArrayComponent extends NestedDataComponent {
2
2
  static savedValueTypes(): string[];
3
3
  componentContext(component: any): any;
4
4
  get iteratableRows(): void;
5
+ set rowIndex(value: number | undefined);
6
+ get rowIndex(): number | undefined;
5
7
  prevHasAddButton: any;
6
8
  checkAddButtonChanged(): void;
7
9
  checkData(data: any, flags: any, row: any): any;
@@ -10,7 +12,6 @@ export default class NestedArrayComponent extends NestedDataComponent {
10
12
  checkRow(...args: any[]): any;
11
13
  processRow(method: any, data: any, opts: any, row: any, components: any, silentCheck: any): any;
12
14
  hasAddButton(): any;
13
- getComponent(path: any, fn: any, originalPath: any): any;
14
15
  everyComponent(fn: any, rowIndex: any, options?: {}): void;
15
16
  getComponents(rowIndex: any): any;
16
17
  removeSubmissionMetadataRow(index: any): void;
@@ -1,6 +1,8 @@
1
1
  'use strict';
2
2
  import _ from 'lodash';
3
- import { componentValueTypes, getStringFromComponentPath } from '../../../utils/utils';
3
+ import { Utils } from '@formio/core/utils';
4
+ const { getComponentPaths } = Utils;
5
+ import { componentValueTypes, isLayoutComponent } from '../../../utils/utils';
4
6
  import Component from '../component/Component';
5
7
  import NestedDataComponent from '../nesteddata/NestedDataComponent';
6
8
  export default class NestedArrayComponent extends NestedDataComponent {
@@ -19,9 +21,13 @@ export default class NestedArrayComponent extends NestedDataComponent {
19
21
  throw new Error('Getter #iteratableRows() is not implemented');
20
22
  }
21
23
  get rowIndex() {
22
- return super.rowIndex;
24
+ return this._rowIndex;
23
25
  }
24
26
  set rowIndex(value) {
27
+ this.paths = getComponentPaths(this.component, this.parent?.component, {
28
+ ...(this.parent?.paths || {}),
29
+ ...{ dataIndex: value }
30
+ });
25
31
  this._rowIndex = value;
26
32
  }
27
33
  init() {
@@ -84,47 +90,6 @@ export default class NestedArrayComponent extends NestedDataComponent {
84
90
  value: this.dataValue,
85
91
  }, 'show'));
86
92
  }
87
- getComponent(path, fn, originalPath) {
88
- originalPath = originalPath || getStringFromComponentPath(path);
89
- if (this.componentsMap.hasOwnProperty(originalPath)) {
90
- if (fn) {
91
- return fn(this.componentsMap[originalPath]);
92
- }
93
- else {
94
- return this.componentsMap[originalPath];
95
- }
96
- }
97
- path = Array.isArray(path) ? path : [path];
98
- let key = path.shift();
99
- const remainingPath = path;
100
- let result = [];
101
- let possibleComp = null;
102
- let comp = null;
103
- let rowIndex = null;
104
- if (_.isNumber(key)) {
105
- rowIndex = key;
106
- key = remainingPath.shift();
107
- }
108
- if (!_.isString(key)) {
109
- return result;
110
- }
111
- this.everyComponent((component, components) => {
112
- if (component.component.key === key) {
113
- possibleComp = component;
114
- if (remainingPath.length > 0 && 'getComponent' in component) {
115
- comp = component.getComponent(remainingPath, fn, originalPath);
116
- }
117
- else if (fn) {
118
- fn(component, components);
119
- }
120
- result = rowIndex !== null ? comp : result.concat(comp || possibleComp);
121
- }
122
- }, rowIndex);
123
- if ((!result || result.length === 0) && possibleComp) {
124
- result = rowIndex !== null ? possibleComp : [possibleComp];
125
- }
126
- return result;
127
- }
128
93
  everyComponent(fn, rowIndex, options = {}) {
129
94
  if (_.isObject(rowIndex)) {
130
95
  options = rowIndex;
@@ -85,7 +85,6 @@ export default class DataGridComponent extends NestedArrayComponent {
85
85
  show: boolean;
86
86
  };
87
87
  checkComponentConditions(data: any, flags: any, row: any): boolean;
88
- getComponent(path: any, fn: any): any;
89
88
  toggleGroup(element: any, index: any): void;
90
89
  }
91
90
  import NestedArrayComponent from '../_classes/nestedarray/NestedArrayComponent';
@@ -1,7 +1,6 @@
1
1
  import _ from 'lodash';
2
2
  import NestedArrayComponent from '../_classes/nestedarray/NestedArrayComponent';
3
3
  import { fastCloneDeep, getFocusableElements } from '../../utils/utils';
4
- import Components from '../Components';
5
4
  import dragula from 'dragula';
6
5
  export default class DataGridComponent extends NestedArrayComponent {
7
6
  static schema(...extend) {
@@ -407,7 +406,6 @@ export default class DataGridComponent extends NestedArrayComponent {
407
406
  }
408
407
  component.rowIndex = rowIndex;
409
408
  component.row = `${rowIndex}-${colIndex}`;
410
- component.path = Components.getComponentPath(component);
411
409
  });
412
410
  }
413
411
  updateRowsComponents(rowIndex) {
@@ -473,6 +471,7 @@ export default class DataGridComponent extends NestedArrayComponent {
473
471
  const options = _.clone(this.options);
474
472
  options.name += `[${rowIndex}]`;
475
473
  options.row = `${rowIndex}-${colIndex}`;
474
+ options.rowIndex = rowIndex;
476
475
  let columnComponent;
477
476
  if (this.builderMode) {
478
477
  col.id = col.id + rowIndex;
@@ -595,49 +594,6 @@ export default class DataGridComponent extends NestedArrayComponent {
595
594
  restoreComponentsContext() {
596
595
  this.rows.forEach((row, index) => _.forIn(row, (component) => component.data = this.dataValue[index]));
597
596
  }
598
- getComponent(path, fn) {
599
- path = Array.isArray(path) ? path : [path];
600
- const [key, ...remainingPath] = path;
601
- let result = [];
602
- if (_.isNumber(key) && remainingPath.length) {
603
- const compKey = remainingPath.pop();
604
- result = this.rows[key][compKey];
605
- // If the component is inside a Layout Component, try to find it among all the row's components
606
- if (!result) {
607
- Object.entries(this.rows[key]).forEach(([, comp]) => {
608
- if ('getComponent' in comp) {
609
- const possibleResult = comp.getComponent([compKey], fn);
610
- if (possibleResult) {
611
- result = possibleResult;
612
- }
613
- }
614
- });
615
- }
616
- if (result && _.isFunction(fn)) {
617
- fn(result, this.getComponents());
618
- }
619
- if (remainingPath.length && 'getComponent' in result) {
620
- return result.getComponent(remainingPath, fn);
621
- }
622
- return result;
623
- }
624
- if (!_.isString(key)) {
625
- return result;
626
- }
627
- this.everyComponent((component, components) => {
628
- if (component.component.key === key) {
629
- let comp = component;
630
- if (remainingPath.length > 0 && 'getComponent' in component) {
631
- comp = component.getComponent(remainingPath, fn);
632
- }
633
- else if (fn) {
634
- fn(component, components);
635
- }
636
- result = result.concat(comp);
637
- }
638
- });
639
- return result.length > 0 ? result : null;
640
- }
641
597
  toggleGroup(element, index) {
642
598
  element.classList.toggle('collapsed');
643
599
  _.each(this.refs.chunks[index], row => {
@@ -3,7 +3,6 @@ import DataGridComponent from '../datagrid/DataGrid';
3
3
  import _ from 'lodash';
4
4
  import EventEmitter from 'eventemitter3';
5
5
  import { componentValueTypes, getComponentSavedTypes, uniqueKey } from '../../utils/utils';
6
- import Components from '../Components';
7
6
  export default class DataMapComponent extends DataGridComponent {
8
7
  static schema(...extend) {
9
8
  return Component.schema({
@@ -227,6 +226,7 @@ export default class DataMapComponent extends DataGridComponent {
227
226
  options.events = new EventEmitter();
228
227
  options.name += `[${rowIndex}]`;
229
228
  options.row = `${rowIndex}`;
229
+ options.rowIndex = rowIndex;
230
230
  const components = {};
231
231
  components['__key'] = this.createComponent(this.keySchema, options, { __key: this.builderMode ? this.defaultRowKey : key });
232
232
  components['__key'].on('componentChange', (event) => {
@@ -236,7 +236,6 @@ export default class DataMapComponent extends DataGridComponent {
236
236
  delete dataValue[key];
237
237
  const comp = components[this.valueKey];
238
238
  comp.component.key = newKey;
239
- comp.path = Components.getComponentPath(comp);
240
239
  key = newKey;
241
240
  });
242
241
  const valueComponent = _.clone(this.component.valueComponent);