@formio/js 5.0.0-dev.5932.9b8cb6d → 5.0.0-dev.5933.3445318

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 (85) hide show
  1. package/Changelog.md +302 -10
  2. package/README.md +28 -1
  3. package/dist/formio.form.js +585 -595
  4. package/dist/formio.form.min.js +1 -1
  5. package/dist/formio.form.min.js.LICENSE.txt +2 -4
  6. package/dist/formio.full.js +586 -596
  7. package/dist/formio.full.min.js +1 -1
  8. package/dist/formio.full.min.js.LICENSE.txt +2 -4
  9. package/dist/formio.js +3006 -287
  10. package/dist/formio.min.js +1 -1
  11. package/dist/formio.min.js.LICENSE.txt +13 -1
  12. package/dist/formio.utils.js +41 -51
  13. package/dist/formio.utils.min.js +1 -1
  14. package/dist/formio.utils.min.js.LICENSE.txt +2 -4
  15. package/lib/cjs/Webform.d.ts +1 -1
  16. package/lib/cjs/Webform.js +27 -28
  17. package/lib/cjs/WebformBuilder.js +6 -13
  18. package/lib/cjs/Wizard.js +15 -20
  19. package/lib/cjs/components/Components.d.ts +0 -7
  20. package/lib/cjs/components/Components.js +1 -33
  21. package/lib/cjs/components/_classes/component/Component.d.ts +39 -7
  22. package/lib/cjs/components/_classes/component/Component.js +97 -29
  23. package/lib/cjs/components/_classes/component/editForm/Component.edit.data.js +2 -2
  24. package/lib/cjs/components/_classes/componentModal/ComponentModal.d.ts +1 -0
  25. package/lib/cjs/components/_classes/componentModal/ComponentModal.js +1 -0
  26. package/lib/cjs/components/_classes/nested/NestedComponent.d.ts +4 -19
  27. package/lib/cjs/components/_classes/nested/NestedComponent.js +54 -60
  28. package/lib/cjs/components/_classes/nestedarray/NestedArrayComponent.d.ts +2 -1
  29. package/lib/cjs/components/_classes/nestedarray/NestedArrayComponent.js +9 -46
  30. package/lib/cjs/components/datagrid/DataGrid.d.ts +0 -1
  31. package/lib/cjs/components/datagrid/DataGrid.js +5 -46
  32. package/lib/cjs/components/datamap/DataMap.js +2 -3
  33. package/lib/cjs/components/editgrid/EditGrid.d.ts +1 -1
  34. package/lib/cjs/components/editgrid/EditGrid.js +20 -15
  35. package/lib/cjs/components/form/Form.d.ts +2 -3
  36. package/lib/cjs/components/form/Form.js +26 -28
  37. package/lib/cjs/components/html/HTML.js +15 -3
  38. package/lib/cjs/components/number/Number.js +11 -4
  39. package/lib/cjs/components/selectboxes/SelectBoxes.js +0 -1
  40. package/lib/cjs/formio.form.js +1 -0
  41. package/lib/cjs/utils/conditionOperators/DateGreaterThan.js +2 -2
  42. package/lib/cjs/utils/conditionOperators/IsEmptyValue.d.ts +2 -2
  43. package/lib/cjs/utils/conditionOperators/IsEmptyValue.js +2 -2
  44. package/lib/cjs/utils/conditionOperators/IsEqualTo.d.ts +2 -2
  45. package/lib/cjs/utils/conditionOperators/IsEqualTo.js +2 -2
  46. package/lib/cjs/utils/formUtils.d.ts +25 -14
  47. package/lib/cjs/utils/formUtils.js +11 -16
  48. package/lib/cjs/utils/utils.d.ts +1 -2
  49. package/lib/cjs/utils/utils.js +15 -31
  50. package/lib/mjs/Webform.d.ts +1 -1
  51. package/lib/mjs/Webform.js +24 -27
  52. package/lib/mjs/WebformBuilder.js +6 -13
  53. package/lib/mjs/Wizard.js +13 -17
  54. package/lib/mjs/components/Components.d.ts +0 -7
  55. package/lib/mjs/components/Components.js +1 -32
  56. package/lib/mjs/components/_classes/component/Component.d.ts +39 -7
  57. package/lib/mjs/components/_classes/component/Component.js +99 -30
  58. package/lib/mjs/components/_classes/component/editForm/Component.edit.data.js +2 -2
  59. package/lib/mjs/components/_classes/componentModal/ComponentModal.d.ts +1 -0
  60. package/lib/mjs/components/_classes/componentModal/ComponentModal.js +1 -0
  61. package/lib/mjs/components/_classes/nested/NestedComponent.d.ts +4 -19
  62. package/lib/mjs/components/_classes/nested/NestedComponent.js +55 -61
  63. package/lib/mjs/components/_classes/nestedarray/NestedArrayComponent.d.ts +2 -1
  64. package/lib/mjs/components/_classes/nestedarray/NestedArrayComponent.js +8 -43
  65. package/lib/mjs/components/datagrid/DataGrid.d.ts +0 -1
  66. package/lib/mjs/components/datagrid/DataGrid.js +5 -46
  67. package/lib/mjs/components/datamap/DataMap.js +2 -3
  68. package/lib/mjs/components/editgrid/EditGrid.d.ts +1 -1
  69. package/lib/mjs/components/editgrid/EditGrid.js +22 -14
  70. package/lib/mjs/components/form/Form.d.ts +2 -3
  71. package/lib/mjs/components/form/Form.js +26 -28
  72. package/lib/mjs/components/html/HTML.js +15 -3
  73. package/lib/mjs/components/number/Number.js +11 -4
  74. package/lib/mjs/components/selectboxes/SelectBoxes.js +0 -1
  75. package/lib/mjs/formio.form.js +1 -0
  76. package/lib/mjs/utils/conditionOperators/DateGreaterThan.js +2 -2
  77. package/lib/mjs/utils/conditionOperators/IsEmptyValue.d.ts +2 -2
  78. package/lib/mjs/utils/conditionOperators/IsEmptyValue.js +2 -2
  79. package/lib/mjs/utils/conditionOperators/IsEqualTo.d.ts +2 -2
  80. package/lib/mjs/utils/conditionOperators/IsEqualTo.js +2 -2
  81. package/lib/mjs/utils/formUtils.d.ts +25 -14
  82. package/lib/mjs/utils/formUtils.js +2 -12
  83. package/lib/mjs/utils/utils.d.ts +1 -2
  84. package/lib/mjs/utils/utils.js +14 -29
  85. package/package.json +4 -4
@@ -1,6 +1,8 @@
1
1
  'use strict';
2
2
  import _ from 'lodash';
3
- import { componentValueTypes, getStringFromComponentPath, isLayoutComponent } 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;
@@ -87,7 +87,6 @@ export default class DataGridComponent extends NestedArrayComponent {
87
87
  show: boolean;
88
88
  };
89
89
  checkComponentConditions(data: any, flags: any, row: any): boolean;
90
- getComponent(path: any, fn: any): any;
91
90
  toggleGroup(element: any, index: any): void;
92
91
  }
93
92
  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
  export default class DataGridComponent extends NestedArrayComponent {
6
5
  static schema(...extend) {
7
6
  return NestedArrayComponent.schema({
@@ -409,7 +408,7 @@ export default class DataGridComponent extends NestedArrayComponent {
409
408
  row
410
409
  });
411
410
  this.checkConditions();
412
- this.triggerChange();
411
+ this.triggerChange({ modified: true });
413
412
  this.redraw().then(() => {
414
413
  this.focusOnNewRowElement(this.rows[index]);
415
414
  });
@@ -422,7 +421,6 @@ export default class DataGridComponent extends NestedArrayComponent {
422
421
  }
423
422
  component.rowIndex = rowIndex;
424
423
  component.row = `${rowIndex}-${colIndex}`;
425
- component.path = Components.getComponentPath(component);
426
424
  });
427
425
  }
428
426
  updateRowsComponents(rowIndex) {
@@ -488,6 +486,10 @@ export default class DataGridComponent extends NestedArrayComponent {
488
486
  const options = _.clone(this.options);
489
487
  options.name += `[${rowIndex}]`;
490
488
  options.row = `${rowIndex}-${colIndex}`;
489
+ options.rowIndex = rowIndex;
490
+ options.onChange = (flags, changed, modified) => {
491
+ this.triggerChange({ modified });
492
+ };
491
493
  let columnComponent;
492
494
  if (this.builderMode) {
493
495
  col.id = col.id + rowIndex;
@@ -610,49 +612,6 @@ export default class DataGridComponent extends NestedArrayComponent {
610
612
  restoreComponentsContext() {
611
613
  this.rows.forEach((row, index) => _.forIn(row, (component) => component.data = this.dataValue[index]));
612
614
  }
613
- getComponent(path, fn) {
614
- path = Array.isArray(path) ? path : [path];
615
- const [key, ...remainingPath] = path;
616
- let result = [];
617
- if (_.isNumber(key) && remainingPath.length) {
618
- const compKey = remainingPath.pop();
619
- result = this.rows[key][compKey];
620
- // If the component is inside a Layout Component, try to find it among all the row's components
621
- if (!result) {
622
- Object.entries(this.rows[key]).forEach(([, comp]) => {
623
- if ('getComponent' in comp) {
624
- const possibleResult = comp.getComponent([compKey], fn);
625
- if (possibleResult) {
626
- result = possibleResult;
627
- }
628
- }
629
- });
630
- }
631
- if (result && _.isFunction(fn)) {
632
- fn(result, this.getComponents());
633
- }
634
- if (remainingPath.length && 'getComponent' in result) {
635
- return result.getComponent(remainingPath, fn);
636
- }
637
- return result;
638
- }
639
- if (!_.isString(key)) {
640
- return result;
641
- }
642
- this.everyComponent((component, components) => {
643
- if (component.component.key === key) {
644
- let comp = component;
645
- if (remainingPath.length > 0 && 'getComponent' in component) {
646
- comp = component.getComponent(remainingPath, fn);
647
- }
648
- else if (fn) {
649
- fn(component, components);
650
- }
651
- result = result.concat(comp);
652
- }
653
- });
654
- return result.length > 0 ? result : null;
655
- }
656
615
  toggleGroup(element, index) {
657
616
  element.classList.toggle('collapsed');
658
617
  _.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({
@@ -70,7 +69,7 @@ export default class DataMapComponent extends DataGridComponent {
70
69
  }
71
70
  get dataValue() {
72
71
  if (!this.key ||
73
- (!this.visible && this.component.clearOnHide)) {
72
+ (this.conditionallyHidden && this.component.clearOnHide)) {
74
73
  return this.emptyValue;
75
74
  }
76
75
  if (!this.hasValue() && this.shouldAddDefaultValue) {
@@ -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);
@@ -43,7 +43,7 @@ export default class EditGridComponent extends NestedArrayComponent {
43
43
  get defaultValue(): any[];
44
44
  hasRemoveButtons(): boolean;
45
45
  editRows: any;
46
- checkRowVariableTypeComponents(editRow: any, rowIndex: any): void;
46
+ checkRowVariableTypeComponents(editRow: any, rowIndex: any): boolean;
47
47
  setVariableTypeComponents(): void;
48
48
  variableTypeComponentsIndexes: any[] | undefined;
49
49
  isOpen(editRow: any): boolean;
@@ -289,12 +289,15 @@ export default class EditGridComponent extends NestedArrayComponent {
289
289
  }
290
290
  checkRowVariableTypeComponents(editRow, rowIndex) {
291
291
  const rowComponents = editRow.components;
292
+ let typeChanged = false;
292
293
  if (_.some(this.variableTypeComponentsIndexes, (compIndex) => {
293
294
  const variableTypeComp = rowComponents[compIndex];
294
295
  return variableTypeComp.type !== variableTypeComp.component.type;
295
296
  })) {
296
297
  editRow.components = this.createRowComponents(editRow.data, rowIndex, true);
298
+ typeChanged = true;
297
299
  }
300
+ return typeChanged;
298
301
  }
299
302
  setVariableTypeComponents() {
300
303
  //set components which type is changing within a row (e.g.,by mergeComponentSchema action)
@@ -923,6 +926,7 @@ export default class EditGridComponent extends NestedArrayComponent {
923
926
  const options = _.clone(this.options);
924
927
  options.name += `[${rowIndex}]`;
925
928
  options.row = `${rowIndex}-${colIndex}`;
929
+ options.rowIndex = rowIndex;
926
930
  options.onChange = (flags = {}, changed, modified) => {
927
931
  if (changed.instance.root?.id && (this.root?.id !== changed.instance.root.id)) {
928
932
  changed.instance.root.triggerChange(flags, changed, modified);
@@ -939,11 +943,13 @@ export default class EditGridComponent extends NestedArrayComponent {
939
943
  ...flags,
940
944
  changed,
941
945
  }, editRow.data, editRow.components);
942
- this.validateRow(editRow, false);
946
+ this.validateRow(editRow, false, false);
943
947
  }
944
948
  if (this.variableTypeComponentsIndexes.length) {
945
- this.checkRowVariableTypeComponents(editRow, rowIndex);
946
- this.redraw();
949
+ const typeChanged = this.checkRowVariableTypeComponents(editRow, rowIndex);
950
+ if (typeChanged) {
951
+ this.redraw();
952
+ }
947
953
  }
948
954
  };
949
955
  const comp = this.createComponent(_.assign({}, column, { row: options.row }), options, row, null, recreatePartially && currentRowComponents ? currentRowComponents[colIndex] : null);
@@ -979,22 +985,24 @@ export default class EditGridComponent extends NestedArrayComponent {
979
985
  validateRow(editRow, dirty, forceSilentCheck, fromSubmission) {
980
986
  editRow.errors = [];
981
987
  if (this.shouldValidateRow(editRow, dirty, fromSubmission)) {
982
- const silentCheck = (this.component.rowDrafts && !this.shouldValidateDraft(editRow)) || forceSilentCheck;
988
+ const silentCheck = forceSilentCheck === false ? false : ((this.component.rowDrafts && !this.shouldValidateDraft(editRow)) || forceSilentCheck);
983
989
  const rootValue = fastCloneDeep(this.rootValue);
984
990
  const editGridValue = _.get(rootValue, this.path, []);
985
991
  editGridValue[editRow.rowIndex] = editRow.data;
986
992
  _.set(rootValue, this.path, editGridValue);
987
993
  const validationProcessorProcess = (context) => this.validationProcessor(context, { dirty, silentCheck });
988
994
  const errors = processSync({
989
- components: fastCloneDeep(this.component.components).map((component) => {
990
- component.parentPath = `${this.path}[${editRow.rowIndex}]`;
991
- return component;
992
- }),
995
+ components: this.component.components,
993
996
  data: rootValue,
994
997
  row: editRow.data,
995
998
  process: 'validateRow',
996
999
  instances: this.componentsMap,
997
1000
  scope: { errors: [] },
1001
+ parent: this.component,
1002
+ parentPaths: {
1003
+ ...this.paths,
1004
+ dataIndex: editRow.rowIndex
1005
+ },
998
1006
  processors: [
999
1007
  {
1000
1008
  process: validationProcessorProcess,
@@ -1026,9 +1034,12 @@ export default class EditGridComponent extends NestedArrayComponent {
1026
1034
  });
1027
1035
  }
1028
1036
  }
1029
- if (!this.component.rowDrafts || this.root?.submitted) {
1037
+ if (editRow.alerts && (!this.component.rowDrafts || this.root?.submitted)) {
1030
1038
  this.showRowErrorAlerts(editRow, editRow.errors);
1031
1039
  }
1040
+ else if (editRow.errors?.length) {
1041
+ this.setCustomValidity(editRow.errors, dirty);
1042
+ }
1032
1043
  return editRow.errors;
1033
1044
  }
1034
1045
  showRowErrorAlerts(editRow, errors) {
@@ -1139,7 +1150,7 @@ export default class EditGridComponent extends NestedArrayComponent {
1139
1150
  }
1140
1151
  }
1141
1152
  const changed = this.hasChanged(value, this.dataValue);
1142
- if (this.parent && !this.options.server) {
1153
+ if (this.parent) {
1143
1154
  this.parent.checkComponentConditions();
1144
1155
  }
1145
1156
  this.dataValue = value;
@@ -1172,10 +1183,7 @@ export default class EditGridComponent extends NestedArrayComponent {
1172
1183
  this.editRows = this.editRows.slice(0, dataLength);
1173
1184
  this.openWhenEmpty();
1174
1185
  this.updateOnChange(flags, changed);
1175
- // do not call checkData with server option, it is called when change is triggered in updateOnChange
1176
- if (!this.options.server) {
1177
- this.checkData();
1178
- }
1186
+ this.checkData();
1179
1187
  this.changeState(changed, flags);
1180
1188
  return changed;
1181
1189
  }
@@ -21,7 +21,7 @@ export default class FormComponent extends Component {
21
21
  get useOriginalRevision(): any;
22
22
  setFormRevision(rev: any): void;
23
23
  subFormRevision: any;
24
- getComponent(path: any, fn: any): any;
24
+ getComponent(path: any): any;
25
25
  getSubOptions(options?: {}): {};
26
26
  render(): string;
27
27
  asString(value: any): any;
@@ -32,6 +32,7 @@ export default class FormComponent extends Component {
32
32
  attach(element: any): Promise<void>;
33
33
  get hasLoadedForm(): any;
34
34
  get isRevisionChanged(): any;
35
+ get subFormData(): any;
35
36
  subFormReady: Promise<any> | null | undefined;
36
37
  /**
37
38
  * Pass everyComponent to subform.
@@ -55,8 +56,6 @@ export default class FormComponent extends Component {
55
56
  */
56
57
  loadSubForm(fromAttach: boolean): Promise<any>;
57
58
  subFormLoading: boolean | undefined;
58
- get subFormData(): any;
59
- checkComponentValidity(data: any, dirty: any, row: any, options: any, errors?: any[]): any;
60
59
  checkComponentConditions(data: any, flags: any, row: any): any;
61
60
  calculateValue(data: any, flags: any, row: any): any;
62
61
  setPristine(pristine: any): void;
@@ -3,7 +3,7 @@ import _ from 'lodash';
3
3
  import Component from '../_classes/component/Component';
4
4
  import ComponentModal from '../_classes/componentModal/ComponentModal';
5
5
  import EventEmitter from 'eventemitter3';
6
- import { isMongoId, eachComponent, getStringFromComponentPath, getArrayFromComponentPath, componentValueTypes } from '../../utils/utils';
6
+ import { isMongoId, eachComponent, componentValueTypes } from '../../utils/utils';
7
7
  import { Formio } from '../../Formio';
8
8
  import Form from '../../Form';
9
9
  export default class FormComponent extends Component {
@@ -127,21 +127,19 @@ export default class FormComponent extends Component {
127
127
  this.subFormRevision = undefined;
128
128
  }
129
129
  }
130
- getComponent(path, fn) {
131
- path = getArrayFromComponentPath(path);
132
- if (path[0] === 'data') {
133
- path.shift();
134
- }
135
- const originalPathStr = `${this.path}.data.${getStringFromComponentPath(path)}`;
136
- if (this.subForm) {
137
- return this.subForm.getComponent(path, fn, originalPathStr);
130
+ getComponent(path) {
131
+ if (!this.subForm) {
132
+ return null;
138
133
  }
134
+ return this.subForm.getComponent(path);
139
135
  }
140
136
  /* eslint-disable max-statements */
141
137
  getSubOptions(options = {}) {
142
138
  options.events = this.createEmitter();
143
139
  // Make sure to not show the submit button in wizards in the nested forms.
144
140
  _.set(options, 'buttonSettings.showSubmit', false);
141
+ // Set the parent option to the subform so those references are stable when the subform is created
142
+ options.parent = this;
145
143
  if (!this.options) {
146
144
  return options;
147
145
  }
@@ -203,6 +201,7 @@ export default class FormComponent extends Component {
203
201
  if (this.options.skipDraftRestore) {
204
202
  options.skipDraftRestore = this.options.skipDraftRestore;
205
203
  }
204
+ options.parent = this;
206
205
  return options;
207
206
  }
208
207
  /* eslint-enable max-statements */
@@ -294,6 +293,7 @@ export default class FormComponent extends Component {
294
293
  const modalShouldBeOpened = this.componentModal ? this.componentModal.isOpened : false;
295
294
  const currentValue = modalShouldBeOpened ? this.componentModal.currentValue : this.dataValue;
296
295
  this.componentModal = new ComponentModal(this, element, modalShouldBeOpened, currentValue, this._referenceAttributeName);
296
+ this.subForm.element = this.componentModal.refs.componentContent || this.subForm.element;
297
297
  this.setOpenModalElement();
298
298
  }
299
299
  this.calculateValue();
@@ -329,6 +329,9 @@ export default class FormComponent extends Component {
329
329
  && _.isNumber(this.formObj._vid)
330
330
  && this.formObj._vid !== this.subFormRevision;
331
331
  }
332
+ get subFormData() {
333
+ return this.dataValue?.data || {};
334
+ }
332
335
  destroy(all = false) {
333
336
  if (this.subForm) {
334
337
  this.subForm.destroy(all);
@@ -391,8 +394,11 @@ export default class FormComponent extends Component {
391
394
  return (new Form(form, this.getSubOptions())).ready.then((instance) => {
392
395
  this.subForm = instance;
393
396
  this.subForm.currentForm = this;
394
- this.subForm.parent = this;
395
397
  this.subForm.parentVisible = this.visible;
398
+ const componentsMap = this.componentsMap;
399
+ const formComponentsMap = this.subForm.componentsMap;
400
+ _.assign(componentsMap, formComponentsMap);
401
+ this.component.components = this.subForm.components.map((comp) => comp.component);
396
402
  this.subForm.on('change', () => {
397
403
  if (this.subForm) {
398
404
  this.dataValue = this.subForm.getValue();
@@ -409,6 +415,8 @@ export default class FormComponent extends Component {
409
415
  this.valueChanged = this.hasSetValue;
410
416
  this.onChange();
411
417
  return this.subForm;
418
+ }).catch((err) => {
419
+ console.log(err);
412
420
  });
413
421
  }).then((subForm) => {
414
422
  this.updateSubWizards(subForm);
@@ -417,10 +425,11 @@ export default class FormComponent extends Component {
417
425
  return this.subFormReady;
418
426
  }
419
427
  hideSubmitButton(component) {
420
- const isSubmitButton = (component.type === 'button') &&
421
- ((component.action === 'submit') || !component.action);
428
+ const isSubmitButton = component.type === 'button' && (component.action === 'submit' || !component.action);
422
429
  if (isSubmitButton) {
423
430
  component.hidden = true;
431
+ // clearOnHide no longer clears from the JSON `hidden` flag, so we make the button conditionally hidden to clear its data
432
+ component.customConditional = 'show = false';
424
433
  }
425
434
  }
426
435
  /**
@@ -429,7 +438,7 @@ export default class FormComponent extends Component {
429
438
  * @returns {Promise} - The promise that resolves when the subform is loaded.
430
439
  */
431
440
  loadSubForm(fromAttach) {
432
- if (this.builderMode || this.isHidden() || (this.isSubFormLazyLoad() && !fromAttach)) {
441
+ if (this.builderMode || this.conditionallyHidden || (this.isSubFormLazyLoad() && !fromAttach)) {
433
442
  return Promise.resolve();
434
443
  }
435
444
  if (this.hasLoadedForm && !this.isRevisionChanged &&
@@ -464,17 +473,6 @@ export default class FormComponent extends Component {
464
473
  }
465
474
  return Promise.resolve();
466
475
  }
467
- get subFormData() {
468
- return this.dataValue?.data || {};
469
- }
470
- checkComponentValidity(data, dirty, row, options, errors = []) {
471
- options = options || {};
472
- const silentCheck = options.silentCheck || false;
473
- if (this.subForm) {
474
- return this.subForm.checkValidity(this.subFormData, dirty, null, silentCheck, errors);
475
- }
476
- return super.checkComponentValidity(data, dirty, row, options, errors);
477
- }
478
476
  checkComponentConditions(data, flags, row) {
479
477
  const visible = super.checkComponentConditions(data, flags, row);
480
478
  // Return if already hidden
@@ -482,14 +480,14 @@ export default class FormComponent extends Component {
482
480
  return visible;
483
481
  }
484
482
  if (this.subForm) {
485
- return this.subForm.checkConditions(this.subFormData);
483
+ return this.subForm.checkConditions(this.subFormData, flags);
486
484
  }
487
485
  // There are few cases when subForm is not loaded when a change is triggered,
488
486
  // so we need to perform checkConditions after it is ready, or some conditional fields might be hidden in View mode
489
487
  else if (this.subFormReady) {
490
488
  this.subFormReady.then(() => {
491
489
  if (this.subForm) {
492
- return this.subForm.checkConditions(this.subFormData);
490
+ return this.subForm.checkConditions(this.subFormData, flags);
493
491
  }
494
492
  });
495
493
  }
@@ -512,7 +510,7 @@ export default class FormComponent extends Component {
512
510
  * @returns {*|boolean} - TRUE if the subform should be submitted, FALSE if it should not.
513
511
  */
514
512
  get shouldSubmit() {
515
- return this.subFormReady && (!this.component.hasOwnProperty('reference') || this.component.reference) && !this.isHidden();
513
+ return this.subFormReady && (!this.component.hasOwnProperty('reference') || this.component.reference) && !this.conditionallyHidden;
516
514
  }
517
515
  /**
518
516
  * Returns the data for the subform.
@@ -539,7 +537,7 @@ export default class FormComponent extends Component {
539
537
  }
540
538
  this.subForm.nosubmit = false;
541
539
  this.subForm.submitted = true;
542
- return this.subForm.submitForm().then(result => {
540
+ return this.subForm.submitForm({}, true).then(result => {
543
541
  this.subForm.loading = false;
544
542
  this.subForm.showAllErrors = false;
545
543
  this.dataValue = result.submission;
@@ -51,9 +51,21 @@ export default class HTMLComponent extends Component {
51
51
  }
52
52
  checkRefreshOn(changed) {
53
53
  super.checkRefreshOn(changed);
54
- if (!this.builderMode && this.component.refreshOnChange && this.element &&
55
- !_.isUndefined(changed) && ((_.isBoolean(changed) && changed) || !_.isEmpty(changed)) &&
56
- this.conditionallyVisible(this.data, this.row)) {
54
+ let visible;
55
+ if (this.hasCondition()) {
56
+ this._conditionallyHidden = this.checkConditionallyHidden();
57
+ visible = !this.conditionallyHidden;
58
+ }
59
+ else {
60
+ visible = !this.component.hidden;
61
+ }
62
+ const shouldSetContent = !this.builderMode
63
+ && this.component.refreshOnChange
64
+ && this.element
65
+ && !_.isUndefined(changed)
66
+ && ((_.isBoolean(changed) && changed) || !_.isEmpty(changed))
67
+ && visible;
68
+ if (shouldSetContent) {
57
69
  this.setContent(this.element, this.renderContent());
58
70
  }
59
71
  }
@@ -168,14 +168,21 @@ export default class NumberComponent extends Input {
168
168
  if (typeof input === 'string') {
169
169
  input = input.split(this.delimiter).join('').replace(this.decimalSeparator, '.');
170
170
  }
171
- let value = parseFloat(input);
172
- if (!_.isNaN(value)) {
171
+ let value;
172
+ if (!_.isNaN(input)) {
173
173
  // Format scientific notation
174
- if (/e/i.test(String(value))) {
174
+ if (/[0-9]+[eE]/.test(String(input))) {
175
+ // Convert to exponential notation will depend on the decimal limit set in the component
176
+ // Example: 1.23e-5 will be converted to 1.23e-5 if decimal limit is set to 2
177
+ // Example: 1.23e5 will be converted to 1.23e+5 if decimal limit is set to 2
178
+ // if decimal limit is 3, 1.23e5 will be converted to 1.230e+5
179
+ // if decimal limit is not set, 1.23e5 will be converted to 1.23000000000000000000e+5
180
+ value = parseFloat(input);
175
181
  value = value.toExponential(this.decimalLimit);
176
182
  }
177
183
  else {
178
- value = String(value).replace('.', this.decimalSeparator);
184
+ value = parseFloat(input);
185
+ value = !_.isNaN(value) ? String(value).replace('.', this.decimalSeparator) : null;
179
186
  }
180
187
  }
181
188
  else {
@@ -276,7 +276,6 @@ export default class SelectBoxesComponent extends RadioComponent {
276
276
  else {
277
277
  return super.setCustomValidity(messages, dirty, external);
278
278
  }
279
- ;
280
279
  }
281
280
  validateValueAvailability(setting, value) {
282
281
  if (!boolValue(setting) || !value) {
@@ -56,6 +56,7 @@ export function registerModule(mod, defaultFn = null, options = {}) {
56
56
  case 'templates':
57
57
  for (const framework of Object.keys(mod.templates)) {
58
58
  Formio.Templates.extendTemplate(framework, mod.templates[framework]);
59
+ Formio.Templates.defaultTemplates = _.defaults(mod.templates[framework], Formio.Templates.defaultTemplates);
59
60
  }
60
61
  if (mod.templates[current]) {
61
62
  Formio.Templates.current = mod.templates[current];
@@ -14,13 +14,13 @@ export default class DateGeaterThan extends ConditionOperator {
14
14
  return { date, comparedDate };
15
15
  }
16
16
  execute(options, functionName = 'isAfter') {
17
- const { value, instance, conditionComponentPath } = options;
17
+ const { value, instance, path } = options;
18
18
  if (!value) {
19
19
  return false;
20
20
  }
21
21
  let conditionTriggerComponent = null;
22
22
  if (instance?.root?.getComponent) {
23
- conditionTriggerComponent = instance.root.getComponent(conditionComponentPath);
23
+ conditionTriggerComponent = instance.root.getComponent(path);
24
24
  }
25
25
  if (conditionTriggerComponent && conditionTriggerComponent.isPartialDay && conditionTriggerComponent.isPartialDay(value)) {
26
26
  return false;
@@ -1,8 +1,8 @@
1
1
  export default class IsEmptyValue extends ConditionOperator {
2
- execute({ value, instance, conditionComponentPath }: {
2
+ execute({ value, instance, path }: {
3
3
  value: any;
4
4
  instance: any;
5
- conditionComponentPath: any;
5
+ path: any;
6
6
  }): any;
7
7
  getResult(options: any): any;
8
8
  }
@@ -10,10 +10,10 @@ export default class IsEmptyValue extends ConditionOperator {
10
10
  static get requireValue() {
11
11
  return false;
12
12
  }
13
- execute({ value, instance, conditionComponentPath }) {
13
+ execute({ value, instance, path }) {
14
14
  const isEmptyValue = _.isEmpty(_.isNumber(value) ? String(value) : value);
15
15
  if (instance?.root?.getComponent) {
16
- const conditionTriggerComponent = instance.root.getComponent(conditionComponentPath);
16
+ const conditionTriggerComponent = instance.root.getComponent(path);
17
17
  return conditionTriggerComponent?.isEmpty ? conditionTriggerComponent.isEmpty() : isEmptyValue;
18
18
  }
19
19
  return isEmptyValue;
@@ -1,9 +1,9 @@
1
1
  export default class IsEqualTo extends ConditionOperator {
2
- execute({ value, comparedValue, instance, conditionComponentPath }: {
2
+ execute({ value, comparedValue, instance, path }: {
3
3
  value: any;
4
4
  comparedValue: any;
5
5
  instance: any;
6
- conditionComponentPath: any;
6
+ path: any;
7
7
  }): any;
8
8
  }
9
9
  import ConditionOperator from './ConditionOperator';
@@ -8,7 +8,7 @@ export default class IsEqualTo extends ConditionOperator {
8
8
  static get displayedName() {
9
9
  return 'Is Equal To';
10
10
  }
11
- execute({ value, comparedValue, instance, conditionComponentPath }) {
11
+ execute({ value, comparedValue, instance, path }) {
12
12
  if ((value || value === false) && comparedValue && typeof value !== typeof comparedValue && _.isString(comparedValue)) {
13
13
  try {
14
14
  comparedValue = JSON.parse(comparedValue);
@@ -17,7 +17,7 @@ export default class IsEqualTo extends ConditionOperator {
17
17
  catch (e) { }
18
18
  }
19
19
  if (instance?.root?.getComponent) {
20
- const conditionTriggerComponent = instance.root.getComponent(conditionComponentPath);
20
+ const conditionTriggerComponent = instance.root.getComponent(path);
21
21
  if (conditionTriggerComponent
22
22
  && isSelectResourceWithObjectValue(conditionTriggerComponent.component)
23
23
  && conditionTriggerComponent.component?.template) {