@formio/js 5.1.0-dev.6048.569bfc1 → 5.1.0-dev.6049.6110ca0

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 (230) hide show
  1. package/Changelog.md +99 -310
  2. package/README.md +7 -0
  3. package/dist/formio.builder.css +1 -0
  4. package/dist/formio.builder.min.css +1 -1
  5. package/dist/formio.form.css +1 -0
  6. package/dist/formio.form.js +658 -669
  7. package/dist/formio.form.min.css +1 -1
  8. package/dist/formio.form.min.js +1 -1
  9. package/dist/formio.form.min.js.LICENSE.txt +3 -1
  10. package/dist/formio.full.css +1 -0
  11. package/dist/formio.full.js +685 -696
  12. package/dist/formio.full.min.css +1 -1
  13. package/dist/formio.full.min.js +1 -1
  14. package/dist/formio.full.min.js.LICENSE.txt +3 -1
  15. package/dist/formio.js +90 -68
  16. package/dist/formio.min.js +1 -1
  17. package/dist/formio.utils.js +103 -81
  18. package/dist/formio.utils.min.js +1 -1
  19. package/dist/formio.utils.min.js.LICENSE.txt +3 -1
  20. package/lib/cjs/Element.d.ts +2 -1
  21. package/lib/cjs/Element.js +18 -39
  22. package/lib/cjs/EventEmitter.js +2 -25
  23. package/lib/cjs/Form.js +2 -25
  24. package/lib/cjs/PDF.js +1 -1
  25. package/lib/cjs/PDFBuilder.d.ts +1 -0
  26. package/lib/cjs/PDFBuilder.js +10 -11
  27. package/lib/cjs/Webform.d.ts +2 -2
  28. package/lib/cjs/Webform.js +14 -15
  29. package/lib/cjs/WebformBuilder.d.ts +2 -1
  30. package/lib/cjs/WebformBuilder.js +62 -20
  31. package/lib/cjs/Wizard.d.ts +2 -2
  32. package/lib/cjs/Wizard.js +40 -26
  33. package/lib/cjs/WizardBuilder.js +1 -1
  34. package/lib/cjs/components/_classes/component/Component.d.ts +44 -13
  35. package/lib/cjs/components/_classes/component/Component.js +156 -95
  36. package/lib/cjs/components/_classes/component/editForm/Component.edit.conditional.js +1 -1
  37. package/lib/cjs/components/_classes/component/editForm/Component.edit.data.js +19 -0
  38. package/lib/cjs/components/_classes/component/editForm/Component.edit.logic.js +1 -1
  39. package/lib/cjs/components/_classes/component/editForm/utils.js +1 -1
  40. package/lib/cjs/components/_classes/componentModal/ComponentModal.js +1 -1
  41. package/lib/cjs/components/_classes/input/Input.js +1 -1
  42. package/lib/cjs/components/_classes/list/ListComponent.js +3 -3
  43. package/lib/cjs/components/_classes/nested/NestedComponent.form.js +13 -0
  44. package/lib/cjs/components/_classes/nested/NestedComponent.js +15 -8
  45. package/lib/cjs/components/_classes/nestedarray/NestedArrayComponent.js +1 -1
  46. package/lib/cjs/components/_classes/nesteddata/NestedDataComponent.d.ts +0 -2
  47. package/lib/cjs/components/_classes/nesteddata/NestedDataComponent.js +1 -12
  48. package/lib/cjs/components/address/Address.d.ts +8 -0
  49. package/lib/cjs/components/address/Address.js +32 -9
  50. package/lib/cjs/components/address/editForm/Address.edit.display.d.ts +4 -0
  51. package/lib/cjs/components/address/editForm/Address.edit.display.js +1 -0
  52. package/lib/cjs/components/address/editForm/Address.edit.provider.js +8 -8
  53. package/lib/cjs/components/alert/Alert.js +1 -1
  54. package/lib/cjs/components/button/Button.d.ts +1 -1
  55. package/lib/cjs/components/button/Button.js +7 -11
  56. package/lib/cjs/components/checkbox/Checkbox.js +1 -1
  57. package/lib/cjs/components/container/Container.js +1 -1
  58. package/lib/cjs/components/content/editForm/Content.edit.display.js +8 -0
  59. package/lib/cjs/components/currency/Currency.js +1 -1
  60. package/lib/cjs/components/currency/editForm/Currency.edit.display.js +12 -0
  61. package/lib/cjs/components/datagrid/DataGrid.js +5 -1
  62. package/lib/cjs/components/datetime/DateTime.d.ts +1 -1
  63. package/lib/cjs/components/datetime/DateTime.js +15 -13
  64. package/lib/cjs/components/datetime/editForm/DateTime.edit.validation.d.ts +66 -15
  65. package/lib/cjs/components/datetime/editForm/DateTime.edit.validation.js +68 -47
  66. package/lib/cjs/components/day/Day.js +2 -2
  67. package/lib/cjs/components/day/editForm/Day.edit.display.js +8 -0
  68. package/lib/cjs/components/editgrid/EditGrid.js +4 -2
  69. package/lib/cjs/components/editgrid/editForm/EditGrid.edit.display.js +1 -1
  70. package/lib/cjs/components/email/editForm/Email.edit.display.js +12 -0
  71. package/lib/cjs/components/fieldset/editForm/Fieldset.edit.display.js +8 -0
  72. package/lib/cjs/components/file/File.js +6 -2
  73. package/lib/cjs/components/file/editForm/File.edit.file.d.ts +13 -0
  74. package/lib/cjs/components/file/editForm/File.edit.file.js +1 -0
  75. package/lib/cjs/components/form/Form.d.ts +0 -1
  76. package/lib/cjs/components/form/Form.js +31 -23
  77. package/lib/cjs/components/form/editForm/Form.edit.form.js +4 -3
  78. package/lib/cjs/components/hidden/editForm/Hidden.edit.display.js +8 -0
  79. package/lib/cjs/components/html/editForm/HTML.edit.display.js +8 -0
  80. package/lib/cjs/components/number/Number.js +1 -1
  81. package/lib/cjs/components/number/editForm/Number.edit.display.js +12 -0
  82. package/lib/cjs/components/panel/Panel.js +1 -1
  83. package/lib/cjs/components/password/editForm/Password.edit.display.js +13 -1
  84. package/lib/cjs/components/phonenumber/PhoneNumber.form.js +9 -1
  85. package/lib/cjs/components/radio/Radio.d.ts +8 -0
  86. package/lib/cjs/components/radio/Radio.js +16 -6
  87. package/lib/cjs/components/recaptcha/editForm/ReCaptcha.edit.display.js +1 -1
  88. package/lib/cjs/components/select/Select.d.ts +1 -0
  89. package/lib/cjs/components/select/Select.js +21 -5
  90. package/lib/cjs/components/select/editForm/Select.edit.data.d.ts +68 -110
  91. package/lib/cjs/components/select/editForm/Select.edit.data.js +2 -37
  92. package/lib/cjs/components/selectboxes/SelectBoxes.d.ts +6 -0
  93. package/lib/cjs/components/selectboxes/SelectBoxes.js +7 -1
  94. package/lib/cjs/components/signature/Signature.js +1 -1
  95. package/lib/cjs/components/survey/Survey.js +2 -2
  96. package/lib/cjs/components/tabs/editForm/Tabs.edit.display.js +8 -0
  97. package/lib/cjs/components/tags/Tags.js +1 -1
  98. package/lib/cjs/components/textarea/TextArea.js +10 -2
  99. package/lib/cjs/components/textarea/editForm/TextArea.edit.display.js +12 -0
  100. package/lib/cjs/components/textfield/TextField.js +9 -32
  101. package/lib/cjs/components/time/Time.js +1 -1
  102. package/lib/cjs/components/unknown/Unknown.form.d.ts +2 -1
  103. package/lib/cjs/components/unknown/Unknown.form.js +13 -9
  104. package/lib/cjs/components/url/editForm/Url.edit.display.js +12 -0
  105. package/lib/cjs/components/well/editForm/Well.edit.display.js +8 -0
  106. package/lib/cjs/formio.form.js +5 -5
  107. package/lib/cjs/providers/storage/uploadAdapter.js +8 -6
  108. package/lib/cjs/translations/en.d.ts +1 -234
  109. package/lib/cjs/translations/en.js +4 -2
  110. package/lib/cjs/utils/Evaluator.d.ts +20 -6
  111. package/lib/cjs/utils/Evaluator.js +38 -15
  112. package/lib/cjs/utils/builder.js +5 -5
  113. package/lib/cjs/utils/conditionOperators/IsEqualTo.js +3 -3
  114. package/lib/cjs/utils/formUtils.d.ts +2 -2
  115. package/lib/cjs/utils/index.d.ts +169 -2
  116. package/lib/cjs/utils/index.js +22 -2
  117. package/lib/cjs/utils/utils.d.ts +31 -37
  118. package/lib/cjs/utils/utils.js +80 -135
  119. package/lib/cjs/widgets/CalendarWidget.d.ts +1 -8
  120. package/lib/cjs/widgets/CalendarWidget.js +19 -40
  121. package/lib/mjs/Element.d.ts +2 -1
  122. package/lib/mjs/Element.js +11 -9
  123. package/lib/mjs/EventEmitter.js +2 -2
  124. package/lib/mjs/Form.js +1 -1
  125. package/lib/mjs/PDF.js +1 -1
  126. package/lib/mjs/PDFBuilder.d.ts +1 -0
  127. package/lib/mjs/PDFBuilder.js +9 -10
  128. package/lib/mjs/Webform.d.ts +2 -2
  129. package/lib/mjs/Webform.js +12 -13
  130. package/lib/mjs/WebformBuilder.d.ts +2 -1
  131. package/lib/mjs/WebformBuilder.js +53 -13
  132. package/lib/mjs/Wizard.d.ts +2 -2
  133. package/lib/mjs/Wizard.js +38 -24
  134. package/lib/mjs/WizardBuilder.js +1 -1
  135. package/lib/mjs/components/_classes/component/Component.d.ts +44 -13
  136. package/lib/mjs/components/_classes/component/Component.js +129 -45
  137. package/lib/mjs/components/_classes/component/editForm/Component.edit.conditional.js +1 -1
  138. package/lib/mjs/components/_classes/component/editForm/Component.edit.data.js +19 -0
  139. package/lib/mjs/components/_classes/component/editForm/Component.edit.logic.js +1 -1
  140. package/lib/mjs/components/_classes/component/editForm/utils.js +1 -1
  141. package/lib/mjs/components/_classes/componentModal/ComponentModal.js +1 -1
  142. package/lib/mjs/components/_classes/input/Input.js +1 -1
  143. package/lib/mjs/components/_classes/list/ListComponent.js +3 -3
  144. package/lib/mjs/components/_classes/nested/NestedComponent.form.js +13 -0
  145. package/lib/mjs/components/_classes/nested/NestedComponent.js +15 -8
  146. package/lib/mjs/components/_classes/nestedarray/NestedArrayComponent.js +1 -1
  147. package/lib/mjs/components/_classes/nesteddata/NestedDataComponent.d.ts +0 -2
  148. package/lib/mjs/components/_classes/nesteddata/NestedDataComponent.js +1 -12
  149. package/lib/mjs/components/address/Address.d.ts +8 -0
  150. package/lib/mjs/components/address/Address.js +32 -9
  151. package/lib/mjs/components/address/editForm/Address.edit.display.d.ts +4 -0
  152. package/lib/mjs/components/address/editForm/Address.edit.display.js +1 -0
  153. package/lib/mjs/components/address/editForm/Address.edit.provider.js +8 -8
  154. package/lib/mjs/components/alert/Alert.js +1 -1
  155. package/lib/mjs/components/button/Button.d.ts +1 -1
  156. package/lib/mjs/components/button/Button.js +7 -10
  157. package/lib/mjs/components/checkbox/Checkbox.js +1 -1
  158. package/lib/mjs/components/container/Container.js +1 -1
  159. package/lib/mjs/components/content/editForm/Content.edit.display.js +8 -0
  160. package/lib/mjs/components/currency/Currency.js +1 -1
  161. package/lib/mjs/components/currency/editForm/Currency.edit.display.js +12 -0
  162. package/lib/mjs/components/datagrid/DataGrid.js +5 -1
  163. package/lib/mjs/components/datetime/DateTime.d.ts +1 -1
  164. package/lib/mjs/components/datetime/DateTime.js +15 -13
  165. package/lib/mjs/components/datetime/editForm/DateTime.edit.validation.d.ts +66 -15
  166. package/lib/mjs/components/datetime/editForm/DateTime.edit.validation.js +68 -47
  167. package/lib/mjs/components/day/Day.js +2 -2
  168. package/lib/mjs/components/day/editForm/Day.edit.display.js +8 -0
  169. package/lib/mjs/components/editgrid/EditGrid.js +4 -2
  170. package/lib/mjs/components/editgrid/editForm/EditGrid.edit.display.js +1 -1
  171. package/lib/mjs/components/email/editForm/Email.edit.display.js +12 -0
  172. package/lib/mjs/components/fieldset/editForm/Fieldset.edit.display.js +8 -0
  173. package/lib/mjs/components/file/File.js +6 -2
  174. package/lib/mjs/components/file/editForm/File.edit.file.d.ts +13 -0
  175. package/lib/mjs/components/file/editForm/File.edit.file.js +1 -0
  176. package/lib/mjs/components/form/Form.d.ts +0 -1
  177. package/lib/mjs/components/form/Form.js +30 -23
  178. package/lib/mjs/components/form/editForm/Form.edit.form.js +3 -2
  179. package/lib/mjs/components/hidden/editForm/Hidden.edit.display.js +8 -0
  180. package/lib/mjs/components/html/editForm/HTML.edit.display.js +8 -0
  181. package/lib/mjs/components/number/Number.js +1 -1
  182. package/lib/mjs/components/number/editForm/Number.edit.display.js +12 -0
  183. package/lib/mjs/components/panel/Panel.js +1 -1
  184. package/lib/mjs/components/password/editForm/Password.edit.display.js +13 -1
  185. package/lib/mjs/components/phonenumber/PhoneNumber.form.js +9 -1
  186. package/lib/mjs/components/radio/Radio.d.ts +8 -0
  187. package/lib/mjs/components/radio/Radio.js +16 -6
  188. package/lib/mjs/components/recaptcha/editForm/ReCaptcha.edit.display.js +1 -1
  189. package/lib/mjs/components/select/Select.d.ts +1 -0
  190. package/lib/mjs/components/select/Select.js +21 -5
  191. package/lib/mjs/components/select/editForm/Select.edit.data.d.ts +68 -110
  192. package/lib/mjs/components/select/editForm/Select.edit.data.js +2 -37
  193. package/lib/mjs/components/selectboxes/SelectBoxes.d.ts +6 -0
  194. package/lib/mjs/components/selectboxes/SelectBoxes.js +7 -1
  195. package/lib/mjs/components/signature/Signature.js +1 -1
  196. package/lib/mjs/components/survey/Survey.js +2 -2
  197. package/lib/mjs/components/tabs/editForm/Tabs.edit.display.js +8 -0
  198. package/lib/mjs/components/tags/Tags.js +1 -1
  199. package/lib/mjs/components/textarea/TextArea.js +10 -2
  200. package/lib/mjs/components/textarea/editForm/TextArea.edit.display.js +12 -0
  201. package/lib/mjs/components/textfield/TextField.js +3 -3
  202. package/lib/mjs/components/time/Time.js +1 -1
  203. package/lib/mjs/components/unknown/Unknown.form.d.ts +2 -1
  204. package/lib/mjs/components/unknown/Unknown.form.js +13 -9
  205. package/lib/mjs/components/url/editForm/Url.edit.display.js +12 -0
  206. package/lib/mjs/components/well/editForm/Well.edit.display.js +8 -0
  207. package/lib/mjs/formio.form.js +3 -3
  208. package/lib/mjs/providers/storage/uploadAdapter.js +8 -6
  209. package/lib/mjs/translations/en.d.ts +1 -234
  210. package/lib/mjs/translations/en.js +6 -47
  211. package/lib/mjs/utils/Evaluator.d.ts +20 -6
  212. package/lib/mjs/utils/Evaluator.js +31 -13
  213. package/lib/mjs/utils/builder.js +1 -1
  214. package/lib/mjs/utils/conditionOperators/IsEqualTo.js +1 -1
  215. package/lib/mjs/utils/formUtils.d.ts +2 -2
  216. package/lib/mjs/utils/index.d.ts +169 -2
  217. package/lib/mjs/utils/index.js +18 -1
  218. package/lib/mjs/utils/utils.d.ts +31 -37
  219. package/lib/mjs/utils/utils.js +72 -109
  220. package/lib/mjs/widgets/CalendarWidget.d.ts +1 -8
  221. package/lib/mjs/widgets/CalendarWidget.js +19 -40
  222. package/package.json +8 -6
  223. package/lib/cjs/i18n.d.ts +0 -13
  224. package/lib/cjs/i18n.js +0 -19
  225. package/lib/cjs/utils/i18n.d.ts +0 -19
  226. package/lib/cjs/utils/i18n.js +0 -120
  227. package/lib/mjs/i18n.d.ts +0 -13
  228. package/lib/mjs/i18n.js +0 -14
  229. package/lib/mjs/utils/i18n.d.ts +0 -19
  230. package/lib/mjs/utils/i18n.js +0 -112
@@ -5,8 +5,8 @@ import _ from 'lodash';
5
5
  import isMobile from 'ismobilejs';
6
6
  import { processOne, processOneSync, validateProcessInfo } from '@formio/core/process';
7
7
  import { Formio } from '../../../Formio';
8
- import * as FormioUtils from '../../../utils/utils';
9
- import { fastCloneDeep, boolValue, currentTimezone, getScriptPlugin, getContextualRowData } from '../../../utils/utils';
8
+ import FormioUtils from '../../../utils';
9
+ import { fastCloneDeep, boolValue, currentTimezone, getScriptPlugin, getContextualRowData } from '../../../utils';
10
10
  import Element from '../../../Element';
11
11
  import ComponentModal from '../componentModal/ComponentModal';
12
12
  import Widgets from '../../../widgets';
@@ -326,22 +326,6 @@ export default class Component extends Element {
326
326
  * The reference attribute name for this component
327
327
  */
328
328
  this._referenceAttributeName = 'ref';
329
- /**
330
- * Sometimes the customDefaultValue does not set the "value" within the script, but is just a script to execute. This
331
- * flag is used to determine if the customDefaultValue should be used to set the value of the component or not based on
332
- * if there is a "value=" within the script.
333
- */
334
- this.shouldSetCustomDefault = true;
335
- if (this.component.customDefaultValue && (typeof this.component.customDefaultValue === 'string')) {
336
- this.shouldSetCustomDefault = this.component.customDefaultValue.match(/value\s*=/);
337
- }
338
- /**
339
- * Same as customDefaultValue, but for calculateValue.
340
- */
341
- this.shouldSetCalculatedValue = true;
342
- if (this.component.calculateValue && (typeof this.component.calculateValue === 'string')) {
343
- this.shouldSetCalculatedValue = this.component.calculateValue.match(/value\s*=/);
344
- }
345
329
  /**
346
330
  * Used to trigger a new change in this component.
347
331
  * @type {Function} - Call to trigger a change in this component.
@@ -405,7 +389,7 @@ export default class Component extends Element {
405
389
  if (this.allowData && this.key) {
406
390
  this.options.name += `[${this.key}]`;
407
391
  // If component is visible or not set to clear on hide, set the default value.
408
- if (!(this.conditionallyHidden() && this.component.clearOnHide)) {
392
+ if (!this.shouldConditionallyClear()) {
409
393
  if (!this.hasValue()) {
410
394
  if (this.shouldAddDefaultValue) {
411
395
  this.dataValue = this.defaultValue;
@@ -438,10 +422,39 @@ export default class Component extends Element {
438
422
  get componentsMap() {
439
423
  return this.root?.childComponentsMap || {};
440
424
  }
425
+ /**
426
+ * Returns if the parent should conditionally clear.
427
+ * @returns {boolean} - If the parent should conditionally clear.
428
+ */
429
+ parentShouldConditionallyClear() {
430
+ let currentParent = this.parent;
431
+ while (currentParent) {
432
+ if ((currentParent.allowData && currentParent._conditionallyClear) ||
433
+ (!currentParent.allowData && currentParent._conditionallyHidden)) {
434
+ return true;
435
+ }
436
+ currentParent = currentParent.parent;
437
+ }
438
+ return false;
439
+ }
441
440
  parentConditionallyHidden() {
442
441
  let currentParent = this.parent;
443
442
  while (currentParent) {
444
- if (currentParent.conditionallyHidden(true)) {
443
+ if (currentParent._conditionallyHidden) {
444
+ return true;
445
+ }
446
+ currentParent = currentParent.parent;
447
+ }
448
+ return false;
449
+ }
450
+ /**
451
+ * Returns true if any of the parents default their component "hidden" property to true.
452
+ * @returns {boolean} - If any parent defaults the hidden property to true.
453
+ */
454
+ anyParentDefaultsHidden() {
455
+ let currentParent = this.parent;
456
+ while (currentParent) {
457
+ if (currentParent.component.hidden) {
445
458
  return true;
446
459
  }
447
460
  currentParent = currentParent.parent;
@@ -659,11 +672,58 @@ export default class Component extends Element {
659
672
  }
660
673
  return this._logicallyHidden;
661
674
  }
662
- conditionallyHidden(skipParent = false) {
663
- if (!this.hasCondition()) {
664
- return this.logicallyHidden || (skipParent ? false : this.parentConditionallyHidden());
675
+ /**
676
+ * Determines if the component should clear its value when the root form is pristine.
677
+ * @returns {boolean} - If the component should clear its value when the root form is pristine.
678
+ */
679
+ shouldConditionallyClearOnPristine() {
680
+ // If the form is pristine, we should NOT clear the value of a conditionally hidden child component
681
+ // of a layout component that defaults to hidden using the "hidden" component property.
682
+ return !this.anyParentDefaultsHidden();
683
+ }
684
+ /**
685
+ * Returns if the component should clear its value when conditionally hidden.
686
+ * @returns {boolean} - If the component should clear its value when conditionally hidden.
687
+ */
688
+ shouldConditionallyClear() {
689
+ // Skip if this component has clearOnHide set to false.
690
+ if (this.component.clearOnHide === false) {
691
+ this._conditionallyClear = false;
692
+ return this._conditionallyClear;
693
+ }
694
+ // If the component is logically hidden, then it is conditionally hidden and should clear.
695
+ if (this.logicallyHidden) {
696
+ this._conditionallyClear = true;
697
+ return this._conditionallyClear;
698
+ }
699
+ // If we have a condition and it is not conditionally visible, the it should conditionally clear.
700
+ if (this.hasCondition() &&
701
+ !this.conditionallyVisible() &&
702
+ (!this.rootPristine || this.shouldConditionallyClearOnPristine())) {
703
+ this._conditionallyClear = true;
704
+ return this._conditionallyClear;
705
+ }
706
+ this._conditionallyClear = this.hasSetValue ? false : this.parentShouldConditionallyClear();
707
+ return this._conditionallyClear;
708
+ }
709
+ /**
710
+ * Returns if the component is conditionally hidden.
711
+ * @returns {boolean} - If the component is conditionally hidden.
712
+ */
713
+ conditionallyHidden() {
714
+ // If it is logically hidden, then it is conditionally hidden.
715
+ if (this.logicallyHidden) {
716
+ this._conditionallyHidden = true;
717
+ return this._conditionallyHidden;
718
+ }
719
+ // If it has a condition, and is not conditionally visible, then it is conditionally hidden.
720
+ if (this.hasCondition() && !this.conditionallyVisible()) {
721
+ this._conditionallyHidden = true;
722
+ return this._conditionallyHidden;
665
723
  }
666
- return !this.conditionallyVisible() || this.logicallyHidden || (skipParent ? false : this.parentConditionallyHidden());
724
+ // It is conditionally hidden if its parent is conditionally hidden.
725
+ this._conditionallyHidden = this.parentConditionallyHidden();
726
+ return this._conditionallyHidden;
667
727
  }
668
728
  get currentForm() {
669
729
  return this._currentForm;
@@ -2062,7 +2122,7 @@ export default class Component extends Element {
2062
2122
  component: newComponent,
2063
2123
  result,
2064
2124
  });
2065
- if (!_.isEqual(oldValue, newValue) && !(this.component.clearOnHide && this.conditionallyHidden())) {
2125
+ if (!_.isEqual(oldValue, newValue) && !this.shouldConditionallyClear()) {
2066
2126
  this.setValue(newValue);
2067
2127
  if (this.viewOnly) {
2068
2128
  this.dataValue = newValue;
@@ -2095,7 +2155,7 @@ export default class Component extends Element {
2095
2155
  component: newComponent,
2096
2156
  result,
2097
2157
  }, 'value');
2098
- if (!_.isEqual(oldValue, newValue) && !(this.component.clearOnHide && this.conditionallyHidden())) {
2158
+ if (!_.isEqual(oldValue, newValue) && !this.shouldConditionallyClear()) {
2099
2159
  this.setValue(newValue);
2100
2160
  if (this.viewOnly) {
2101
2161
  this.dataValue = newValue;
@@ -2201,7 +2261,7 @@ export default class Component extends Element {
2201
2261
  clearComponentOnHide() {
2202
2262
  // clearOnHide defaults to true for old forms (without the value set) so only trigger if the value is false.
2203
2263
  if (this.component.clearOnHide !== false && !this.options.readOnly && !this.options.showHiddenFields) {
2204
- if (this.conditionallyHidden()) {
2264
+ if (this.shouldConditionallyClear()) {
2205
2265
  this.deleteValue();
2206
2266
  }
2207
2267
  else if (!this.hasValue() && this.shouldAddDefaultValue) {
@@ -2521,16 +2581,30 @@ export default class Component extends Element {
2521
2581
  }
2522
2582
  getCustomDefaultValue(defaultValue) {
2523
2583
  if (this.component.customDefaultValue && !this.options.preview) {
2524
- const customDefaultValue = this.evaluate(this.component.customDefaultValue, { value: '' }, 'value');
2525
- if (this.shouldSetCustomDefault) {
2526
- defaultValue = customDefaultValue;
2527
- }
2584
+ defaultValue = this.evaluate(this.component.customDefaultValue, { value: this.dataValue }, 'value');
2528
2585
  }
2529
2586
  return defaultValue;
2530
2587
  }
2588
+ /**
2589
+ * Returns if a component has a default value set.
2590
+ * @returns {boolean} - TRUE if a default value is set.
2591
+ */
2592
+ get hasDefaultValue() {
2593
+ return this.component.customDefaultValue || (this.component.hasOwnProperty('defaultValue') &&
2594
+ (this.component.defaultValue !== null) &&
2595
+ (this.component.defaultValue !== undefined));
2596
+ }
2597
+ /**
2598
+ * Determine if we should add a default value for this component.
2599
+ * @returns {boolean} - TRUE if a default value should be set
2600
+ */
2531
2601
  get shouldAddDefaultValue() {
2532
- return !this.options.noDefaults || (this.component.defaultValue && !this.isEmpty(this.component.defaultValue)) || this.component.customDefaultValue;
2602
+ return this.pristine && this.allowData && (this.hasDefaultValue || !this.options.noDefaults);
2533
2603
  }
2604
+ /**
2605
+ * Get the default value of this component.
2606
+ * @returns {*} - The default value for this component.
2607
+ */
2534
2608
  get defaultValue() {
2535
2609
  let defaultValue = this.emptyValue;
2536
2610
  if (this.component.defaultValue) {
@@ -2608,13 +2682,16 @@ export default class Component extends Element {
2608
2682
  }
2609
2683
  const isArray = Array.isArray(value);
2610
2684
  const valueInput = this.refs.fileLink || this.refs.input;
2685
+ const isFilelink = !!this.refs.fileLink;
2611
2686
  if (isArray &&
2612
2687
  Array.isArray(this.defaultValue) &&
2613
2688
  this.refs.hasOwnProperty('input') &&
2614
2689
  valueInput &&
2615
2690
  (valueInput.length !== value.length) &&
2616
2691
  this.visible) {
2617
- this.redraw();
2692
+ if (isFilelink || valueInput.length) {
2693
+ this.redraw();
2694
+ }
2618
2695
  }
2619
2696
  if (this.isHtmlRenderMode() && flags && flags.fromSubmission && changed) {
2620
2697
  this.redraw();
@@ -2783,7 +2860,7 @@ export default class Component extends Element {
2783
2860
  return value;
2784
2861
  }
2785
2862
  doValueCalculation(dataValue, data, row) {
2786
- const calculatedValue = this.evaluate(this.component.calculateValue, {
2863
+ return this.evaluate(this.component.calculateValue, {
2787
2864
  value: dataValue,
2788
2865
  data,
2789
2866
  row: row || this.data,
@@ -2791,10 +2868,6 @@ export default class Component extends Element {
2791
2868
  data: this.rootValue
2792
2869
  }
2793
2870
  }, 'value');
2794
- if (this.shouldSetCalculatedValue) {
2795
- return calculatedValue;
2796
- }
2797
- return dataValue;
2798
2871
  }
2799
2872
  /* eslint-disable max-statements */
2800
2873
  calculateComponentValue(data, flags, row) {
@@ -2804,10 +2877,8 @@ export default class Component extends Element {
2804
2877
  }
2805
2878
  // If no calculated value or
2806
2879
  // hidden and set to clearOnHide (Don't calculate a value for a hidden field set to clear when hidden)
2807
- const { clearOnHide } = this.component;
2808
- const shouldBeCleared = this.conditionallyHidden() && clearOnHide;
2809
2880
  const allowOverride = _.get(this.component, 'allowCalculateOverride', false);
2810
- if (shouldBeCleared) {
2881
+ if (this.shouldConditionallyClear()) {
2811
2882
  // remove calculated value so that the value is recalculated once component becomes visible
2812
2883
  if (this.hasOwnProperty('calculatedValue') && allowOverride) {
2813
2884
  _.unset(this, 'calculatedValue');
@@ -2928,9 +2999,11 @@ export default class Component extends Element {
2928
2999
  * @param {boolean} dirty - If the component is dirty.
2929
3000
  * @param {boolean} ignoreCondition - If conditions for the component should be ignored when checking validity.
2930
3001
  * @param {*} row - Contextual row data for this component.
3002
+ * @param {*} options - Additional options for validation.
2931
3003
  * @returns {string} - The message to show when the component is invalid.
2932
3004
  */
2933
- invalidMessage(data, dirty, ignoreCondition, row) {
3005
+ invalidMessage(data, dirty, ignoreCondition, row, options = {}) {
3006
+ const { local } = options;
2934
3007
  if (!row) {
2935
3008
  row = getContextualRowData(this.component, data, this.paths);
2936
3009
  }
@@ -2950,6 +3023,7 @@ export default class Component extends Element {
2950
3023
  component: this.component,
2951
3024
  data,
2952
3025
  row,
3026
+ local,
2953
3027
  path: this.path || this.component.key,
2954
3028
  parent: this.parent?.component,
2955
3029
  paths: this.paths,
@@ -3124,19 +3198,29 @@ export default class Component extends Element {
3124
3198
  data = data || this.rootValue;
3125
3199
  flags = flags || {};
3126
3200
  row = row || this.data;
3201
+ if (flags.noCheck) {
3202
+ return true;
3203
+ }
3204
+ // Some components (for legacy reasons) have calls to "checkData" in inappropriate places such
3205
+ // as setValue. Historically, this was bypassed by a series of cached states around the data model
3206
+ // which caused its own problems. We need to ensure that premium and custom components do not fall into
3207
+ // an infinite loop by only checking this component once.
3208
+ if (this.checkingData) {
3209
+ return;
3210
+ }
3211
+ this.checkingData = true;
3127
3212
  // Needs for Nextgen Rules Engine
3128
3213
  this.resetCaches();
3129
3214
  // Do not trigger refresh if change was triggered on blur event since components with Refresh on Blur have their own listeners
3130
3215
  if (!flags.fromBlur) {
3131
3216
  this.checkRefreshOn(flags.changes, flags);
3132
3217
  }
3133
- if (flags.noCheck) {
3134
- return true;
3135
- }
3136
3218
  this.checkComponentConditions(data, flags, row);
3137
3219
  if (this.id !== flags.triggeredComponentId) {
3138
3220
  this.calculateComponentValue(data, flags, row);
3139
3221
  }
3222
+ // We are done checking data.
3223
+ this.checkingData = false;
3140
3224
  }
3141
3225
  checkModal(errors = [], dirty = false) {
3142
3226
  const messages = errors.filter(error => !error.fromServer);
@@ -1,5 +1,5 @@
1
1
  import EditFormUtils from './utils';
2
- import { getContextComponents } from '../../../../utils/utils';
2
+ import { getContextComponents } from '../../../../utils';
3
3
  /* eslint-disable quotes, max-len */
4
4
  export default [
5
5
  {
@@ -76,6 +76,25 @@ export default [
76
76
  }
77
77
  ]
78
78
  },
79
+ {
80
+ name: 'hide',
81
+ trigger: {
82
+ type: 'javascript',
83
+ javascript: 'result = instance.root.options.editJson === false;'
84
+ },
85
+ actions: [
86
+ {
87
+ name: 'hide',
88
+ type: 'property',
89
+ property: {
90
+ label: 'Hidden',
91
+ value: 'hidden',
92
+ type: 'boolean'
93
+ },
94
+ state: true
95
+ }
96
+ ]
97
+ },
79
98
  {
80
99
  name: 'disabledToolTip',
81
100
  trigger: {
@@ -1,5 +1,5 @@
1
1
  import EditFormUtils from './utils';
2
- import { getContextComponents } from '../../../../utils/utils';
2
+ import { getContextComponents } from '../../../../utils';
3
3
  /* eslint-disable quotes, max-len */
4
4
  export default [
5
5
  {
@@ -6,7 +6,7 @@ const EditFormUtils = {
6
6
  },
7
7
  unifyComponents(objValue, srcValue) {
8
8
  if (objValue.key && srcValue.key) {
9
- if (objValue.skipMerge || srcValue.skipMerge) {
9
+ if ((objValue.skipMerge || srcValue.skipMerge) && !objValue.ignore) {
10
10
  return false;
11
11
  }
12
12
  if (objValue.key === srcValue.key) {
@@ -1,5 +1,5 @@
1
1
  import _ from 'lodash';
2
- import { fastCloneDeep } from '../../../utils/utils';
2
+ import { fastCloneDeep } from '../../../utils';
3
3
  export default class ComponentModal {
4
4
  static render(component, data, topLevel) {
5
5
  const children = component.renderTemplate('component', data, topLevel);
@@ -1,5 +1,5 @@
1
1
  import Multivalue from '../multivalue/Multivalue';
2
- import { convertStringToHTMLElement } from '../../../utils/utils';
2
+ import { convertStringToHTMLElement } from '../../../utils';
3
3
  import Widgets from '../../../widgets';
4
4
  import _ from 'lodash';
5
5
  export default class Input extends Multivalue {
@@ -1,7 +1,7 @@
1
1
  import Field from '../field/Field';
2
2
  import { Formio } from '../../../Formio';
3
3
  import _ from 'lodash';
4
- import { getItemTemplateKeys } from '../../../utils/utils';
4
+ import { getItemTemplateKeys } from '../../../utils';
5
5
  export default class ListComponent extends Field {
6
6
  static schema(...extend) {
7
7
  return Field.schema({
@@ -24,9 +24,9 @@ export default class ListComponent extends Field {
24
24
  get dataReady() {
25
25
  // If the root submission has been set, and we are still not attached, then assume
26
26
  // that our data is ready.
27
- if (this.root &&
27
+ if ((this.root &&
28
28
  this.root.submissionSet &&
29
- !this.attached) {
29
+ !this.attached) || !this.visible) {
30
30
  return Promise.resolve();
31
31
  }
32
32
  return this.itemsLoaded;
@@ -6,6 +6,19 @@ import Components from '../../Components';
6
6
  */
7
7
  export default function (...extend) {
8
8
  return Components.baseEditForm([
9
+ {
10
+ key: 'display',
11
+ components: [
12
+ {
13
+ key: 'labelWidth',
14
+ ignore: true
15
+ },
16
+ {
17
+ key: 'labelMargin',
18
+ ignore: true
19
+ }
20
+ ]
21
+ },
9
22
  {
10
23
  key: 'data',
11
24
  ignore: true
@@ -3,7 +3,7 @@ import _ from 'lodash';
3
3
  import Field from '../field/Field';
4
4
  import Components from '../../Components';
5
5
  '';
6
- import { getComponentPaths, getRandomComponentId, componentMatches, getBestMatch, getStringFromComponentPath } from '../../../utils/utils';
6
+ import FormioUtils from '../../../utils';
7
7
  import { process as processAsync, processSync } from '@formio/core/process';
8
8
  /**
9
9
  * NestedComponent class.
@@ -204,7 +204,7 @@ export default class NestedComponent extends Field {
204
204
  */
205
205
  set rowIndex(value) {
206
206
  this._rowIndex = value;
207
- this.paths = getComponentPaths(this.component, this.parent?.component, {
207
+ this.paths = FormioUtils.getComponentPaths(this.component, this.parent?.component, {
208
208
  ...(this.parent?.paths || {}),
209
209
  ...{ dataIndex: value }
210
210
  });
@@ -308,7 +308,7 @@ export default class NestedComponent extends Field {
308
308
  * @returns {any} - The component that is located.
309
309
  */
310
310
  getComponent(path) {
311
- path = getStringFromComponentPath(path);
311
+ path = FormioUtils.getStringFromComponentPath(path);
312
312
  const matches = {
313
313
  path: undefined,
314
314
  fullPath: undefined,
@@ -320,7 +320,7 @@ export default class NestedComponent extends Field {
320
320
  };
321
321
  this.everyComponent((component) => {
322
322
  // All searches are relative to this component so replace this path from the child paths.
323
- componentMatches(component.component, {
323
+ FormioUtils.componentMatches(component.component, {
324
324
  path: component.paths?.path?.replace(new RegExp(`^${this.paths?.path}\\.?`), ''),
325
325
  fullPath: component.paths?.fullPath?.replace(new RegExp(`^${this.paths?.fullPath}\\.?`), ''),
326
326
  localPath: component.paths?.localPath?.replace(new RegExp(`^${this.paths?.localPath}\\.?`), ''),
@@ -332,7 +332,7 @@ export default class NestedComponent extends Field {
332
332
  return match;
333
333
  });
334
334
  });
335
- return getBestMatch(matches)?.instance;
335
+ return FormioUtils.getBestMatch(matches)?.instance;
336
336
  }
337
337
  /**
338
338
  * Return a component provided the Id of the component.
@@ -374,7 +374,7 @@ export default class NestedComponent extends Field {
374
374
  options.localRoot = this.localRoot;
375
375
  options.skipInit = true;
376
376
  if (!(options.display === 'pdf' && this.builderMode)) {
377
- component.id = getRandomComponentId();
377
+ component.id = FormioUtils.getRandomComponentId();
378
378
  }
379
379
  const comp = Components.create(component, options, data, true);
380
380
  comp.init();
@@ -659,7 +659,7 @@ export default class NestedComponent extends Field {
659
659
  }
660
660
  validationProcessor({ scope, data, row, instance, paths }, flags) {
661
661
  const { dirty } = flags;
662
- if (this.root.hasExtraPages && this.page !== this.root.page) {
662
+ if (this.root.hasSubWizards && this.page !== this.root.page) {
663
663
  instance = this.componentsMap?.hasOwnProperty(paths.dataPath)
664
664
  ? this.componentsMap[paths.dataPath]
665
665
  : this.getComponent(paths.dataPath);
@@ -816,7 +816,7 @@ export default class NestedComponent extends Field {
816
816
  else if (value && component.hasValue(value)) {
817
817
  return component.setValue(_.get(value, component.key), flags);
818
818
  }
819
- else if ((!this.rootPristine || component.visible) && component.shouldAddDefaultValue) {
819
+ else if ((!this.rootPristine || component.visible) && (flags.resetValue || component.shouldAddDefaultValue)) {
820
820
  flags.noValidate = !flags.dirty;
821
821
  flags.resetValue = true;
822
822
  return component.setValue(component.defaultValue, flags);
@@ -826,6 +826,13 @@ export default class NestedComponent extends Field {
826
826
  if (!value) {
827
827
  return false;
828
828
  }
829
+ // If the value is equal to the empty value, then this means we need to reset the values.
830
+ if (_.isEqual(value, this.emptyValue)) {
831
+ // TO-DO: For a future major release, we need to investigate removing the need for the
832
+ // "resetValue" flag. This seems like a hack that is no longer necessary and the renderer
833
+ // may behave more deterministically without it.
834
+ flags.resetValue = true;
835
+ }
829
836
  return this.getComponents().reduce((changed, component) => {
830
837
  return this.setNestedValue(component, value, flags, changed) || changed;
831
838
  }, false);
@@ -2,7 +2,7 @@
2
2
  import _ from 'lodash';
3
3
  import { Utils } from '@formio/core/utils';
4
4
  const { getComponentPaths } = Utils;
5
- import { componentValueTypes, isLayoutComponent } from '../../../utils/utils';
5
+ import { componentValueTypes, isLayoutComponent } from '../../../utils';
6
6
  import Component from '../component/Component';
7
7
  import NestedDataComponent from '../nesteddata/NestedDataComponent';
8
8
  export default class NestedArrayComponent extends NestedDataComponent {
@@ -3,11 +3,9 @@ export default class NestedDataComponent extends NestedComponent {
3
3
  hasChanged(newValue: any, oldValue: any): boolean;
4
4
  get allowData(): boolean;
5
5
  get emptyValue(): {};
6
- get shouldAddDefaultValue(): boolean;
7
6
  componentContext(): any;
8
7
  getValueAsString(value: any, options: any): string;
9
8
  getDataValueAsTable(value: any, options: any): string;
10
- everyComponent(fn: any, options?: {}): void;
11
9
  /**
12
10
  * Get the value of this component.
13
11
  * @returns {any} - Return the value of this component.
@@ -2,7 +2,7 @@
2
2
  import Component from '../component/Component';
3
3
  import NestedComponent from '../nested/NestedComponent';
4
4
  import _ from 'lodash';
5
- import { componentValueTypes, getComponentSavedTypes } from '../../../utils/utils';
5
+ import { componentValueTypes, getComponentSavedTypes } from '../../../utils';
6
6
  export default class NestedDataComponent extends NestedComponent {
7
7
  hasChanged(newValue, oldValue) {
8
8
  // If we do not have a value and are getting set to anything other than undefined or null, then we changed.
@@ -90,17 +90,6 @@ export default class NestedDataComponent extends NestedComponent {
90
90
  `);
91
91
  return result;
92
92
  }
93
- everyComponent(fn, options = {}) {
94
- if (options?.email) {
95
- if (options.fromRoot) {
96
- delete options.fromRoot;
97
- }
98
- else {
99
- return;
100
- }
101
- }
102
- return super.everyComponent(fn, options);
103
- }
104
93
  /**
105
94
  * Get the value of this component.
106
95
  * @returns {any} - Return the value of this component.
@@ -43,6 +43,14 @@ export default class AddressComponent extends ContainerComponent {
43
43
  isValueInLegacyFormat(value: any): any;
44
44
  normalizeValue(value: any): any;
45
45
  get modeSwitcher(): any;
46
+ get providerOptions(): {
47
+ params: any;
48
+ url: any;
49
+ queryProperty: any;
50
+ responseProperty: any;
51
+ displayValueProperty: any;
52
+ autocompleteOptions: any;
53
+ };
46
54
  get removeValueIcon(): any;
47
55
  get searchInput(): any;
48
56
  get addRowButton(): any;
@@ -5,7 +5,7 @@ import { GoogleAddressProvider } from '../../providers/address/GoogleAddressProv
5
5
  import Field from '../_classes/field/Field';
6
6
  import NestedComponent from '../_classes/nested/NestedComponent';
7
7
  import ContainerComponent from '../container/Container';
8
- import { componentValueTypes, getComponentSavedTypes } from '../../utils/utils';
8
+ import { componentValueTypes, getComponentSavedTypes } from '../../utils';
9
9
  export const AddressComponentMode = {
10
10
  Autocomplete: 'autocomplete',
11
11
  Manual: 'manual',
@@ -20,7 +20,6 @@ export default class AddressComponent extends ContainerComponent {
20
20
  key: 'address',
21
21
  switchToManualModeLabel: 'Can\'t find address? Switch to manual mode.',
22
22
  provider: '',
23
- providerOptions: {},
24
23
  manualModeViewString: '',
25
24
  hideLabel: false,
26
25
  disableClearIcon: false,
@@ -113,20 +112,33 @@ export default class AddressComponent extends ContainerComponent {
113
112
  NestedComponent.prototype.addComponents.call(this, this.manualMode ? this.address : {});
114
113
  }
115
114
  Field.prototype.init.call(this);
115
+ // Added for backwards compatibility
116
+ if (this.component.providerOptions) {
117
+ const { params, url, queryProperty, responseProperty, displayValueProperty } = this.component.providerOptions;
118
+ const key = params?.key;
119
+ const autocompleteOptions = params?.autocompleteOptions;
120
+ delete this.component.providerOptions;
121
+ this.component.url = url;
122
+ this.component.queryProperty = queryProperty;
123
+ this.component.responseProperty = responseProperty;
124
+ this.component.displayValueProperty = displayValueProperty;
125
+ this.component.apiKey = key;
126
+ this.component.autocompleteOptions = autocompleteOptions;
127
+ }
128
+ let provider = this.component.provider;
129
+ const providerOptions = this.providerOptions;
130
+ const map = this.component.map;
116
131
  if (!this.builderMode) {
117
- if (this.component.provider) {
118
- const { provider, providerOptions, } = this.component;
132
+ if (provider) {
119
133
  if (_.get(providerOptions, 'params.subscriptionKey')) {
120
134
  _.set(providerOptions, "params['subscription-key']", _.get(providerOptions, 'params.subscriptionKey'));
121
135
  _.unset(providerOptions, 'params.subscriptionKey');
122
136
  }
123
137
  this.provider = this.initializeProvider(provider, providerOptions);
124
138
  }
125
- else if (this.component.map) {
139
+ else if (map) {
126
140
  // Fallback to legacy version where Google Maps was the only provider.
127
- this.component.provider = GoogleAddressProvider.name;
128
- this.component.providerOptions = this.component.providerOptions || {};
129
- const { map, provider, providerOptions, } = this.component;
141
+ provider = this.component.provider = GoogleAddressProvider.name;
130
142
  const { key, region, } = map;
131
143
  if (key) {
132
144
  _.set(providerOptions, 'params.key', key);
@@ -258,6 +270,16 @@ export default class AddressComponent extends ContainerComponent {
258
270
  ? (this.refs[AddressComponent.modeSwitcherRef] || null)
259
271
  : null;
260
272
  }
273
+ get providerOptions() {
274
+ return {
275
+ params: { subscriptionKey: this.component.subscriptionKey, key: this.component.apiKey, ...this.component.params },
276
+ url: this.component.url,
277
+ queryProperty: this.component.queryProperty,
278
+ responseProperty: this.component.responseProperty,
279
+ displayValueProperty: this.component.displayValueProperty,
280
+ autocompleteOptions: this.component.autocompleteOptions
281
+ };
282
+ }
261
283
  get removeValueIcon() {
262
284
  return this.refs
263
285
  ? (this.refs[AddressComponent.removeValueIconRef] || null)
@@ -371,7 +393,8 @@ export default class AddressComponent extends ContainerComponent {
371
393
  const result = ((this.builderMode || this.manualMode) ? super.attach : Field.prototype.attach).call(this, element);
372
394
  if (!this.builderMode) {
373
395
  if (!this.provider && this.component.provider) {
374
- const { provider, providerOptions, } = this.component;
396
+ const provider = this.component.provider;
397
+ const providerOptions = this.providerOptions;
375
398
  this.provider = this.initializeProvider(provider, providerOptions);
376
399
  }
377
400
  }