@formio/js 5.1.0-dev.6040.debc859 → 5.1.0-dev.6042.603237d

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 (236) 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 +661 -672
  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 +688 -699
  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.js +4 -5
  26. package/lib/cjs/Webform.d.ts +2 -2
  27. package/lib/cjs/Webform.js +14 -15
  28. package/lib/cjs/WebformBuilder.d.ts +1 -0
  29. package/lib/cjs/WebformBuilder.js +44 -14
  30. package/lib/cjs/Wizard.d.ts +2 -2
  31. package/lib/cjs/Wizard.js +41 -27
  32. package/lib/cjs/WizardBuilder.js +1 -1
  33. package/lib/cjs/components/_classes/component/Component.d.ts +49 -15
  34. package/lib/cjs/components/_classes/component/Component.js +188 -125
  35. package/lib/cjs/components/_classes/component/editForm/Component.edit.conditional.js +1 -1
  36. package/lib/cjs/components/_classes/component/editForm/Component.edit.data.js +19 -0
  37. package/lib/cjs/components/_classes/component/editForm/Component.edit.logic.js +1 -1
  38. package/lib/cjs/components/_classes/component/editForm/utils.js +1 -1
  39. package/lib/cjs/components/_classes/componentModal/ComponentModal.js +1 -1
  40. package/lib/cjs/components/_classes/input/Input.js +1 -1
  41. package/lib/cjs/components/_classes/list/ListComponent.js +3 -3
  42. package/lib/cjs/components/_classes/nested/NestedComponent.d.ts +0 -1
  43. package/lib/cjs/components/_classes/nested/NestedComponent.form.js +13 -0
  44. package/lib/cjs/components/_classes/nested/NestedComponent.js +17 -25
  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 +9 -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 -4
  62. package/lib/cjs/components/datamap/DataMap.js +2 -6
  63. package/lib/cjs/components/datetime/DateTime.d.ts +1 -1
  64. package/lib/cjs/components/datetime/DateTime.js +15 -13
  65. package/lib/cjs/components/datetime/editForm/DateTime.edit.validation.d.ts +66 -15
  66. package/lib/cjs/components/datetime/editForm/DateTime.edit.validation.js +68 -47
  67. package/lib/cjs/components/day/Day.js +2 -2
  68. package/lib/cjs/components/day/editForm/Day.edit.display.js +8 -0
  69. package/lib/cjs/components/editgrid/EditGrid.js +4 -14
  70. package/lib/cjs/components/editgrid/editForm/EditGrid.edit.display.js +1 -1
  71. package/lib/cjs/components/email/editForm/Email.edit.display.js +12 -0
  72. package/lib/cjs/components/fieldset/editForm/Fieldset.edit.display.js +8 -0
  73. package/lib/cjs/components/file/File.js +6 -2
  74. package/lib/cjs/components/file/editForm/File.edit.file.d.ts +13 -0
  75. package/lib/cjs/components/file/editForm/File.edit.file.js +1 -0
  76. package/lib/cjs/components/form/Form.d.ts +0 -1
  77. package/lib/cjs/components/form/Form.js +32 -24
  78. package/lib/cjs/components/form/editForm/Form.edit.form.js +4 -3
  79. package/lib/cjs/components/hidden/editForm/Hidden.edit.display.js +8 -0
  80. package/lib/cjs/components/html/HTML.js +1 -2
  81. package/lib/cjs/components/html/editForm/HTML.edit.display.js +8 -0
  82. package/lib/cjs/components/number/Number.js +1 -1
  83. package/lib/cjs/components/number/editForm/Number.edit.display.js +12 -0
  84. package/lib/cjs/components/panel/Panel.js +1 -1
  85. package/lib/cjs/components/password/editForm/Password.edit.display.js +13 -1
  86. package/lib/cjs/components/phonenumber/PhoneNumber.form.js +9 -1
  87. package/lib/cjs/components/radio/Radio.d.ts +8 -0
  88. package/lib/cjs/components/radio/Radio.js +17 -7
  89. package/lib/cjs/components/recaptcha/editForm/ReCaptcha.edit.display.js +1 -1
  90. package/lib/cjs/components/select/Select.d.ts +1 -0
  91. package/lib/cjs/components/select/Select.js +21 -5
  92. package/lib/cjs/components/select/editForm/Select.edit.data.d.ts +68 -110
  93. package/lib/cjs/components/select/editForm/Select.edit.data.js +3 -38
  94. package/lib/cjs/components/selectboxes/SelectBoxes.d.ts +6 -0
  95. package/lib/cjs/components/selectboxes/SelectBoxes.js +7 -1
  96. package/lib/cjs/components/signature/Signature.js +1 -1
  97. package/lib/cjs/components/survey/Survey.js +2 -2
  98. package/lib/cjs/components/tabs/Tabs.js +1 -0
  99. package/lib/cjs/components/tabs/editForm/Tabs.edit.display.js +8 -0
  100. package/lib/cjs/components/tags/Tags.js +1 -1
  101. package/lib/cjs/components/textarea/TextArea.js +10 -2
  102. package/lib/cjs/components/textarea/editForm/TextArea.edit.display.js +12 -0
  103. package/lib/cjs/components/textfield/TextField.js +9 -32
  104. package/lib/cjs/components/time/Time.js +1 -1
  105. package/lib/cjs/components/unknown/Unknown.form.d.ts +2 -1
  106. package/lib/cjs/components/unknown/Unknown.form.js +13 -9
  107. package/lib/cjs/components/url/editForm/Url.edit.display.js +12 -0
  108. package/lib/cjs/components/well/editForm/Well.edit.display.js +8 -0
  109. package/lib/cjs/formio.form.js +5 -5
  110. package/lib/cjs/providers/storage/uploadAdapter.js +8 -6
  111. package/lib/cjs/translations/en.d.ts +1 -234
  112. package/lib/cjs/translations/en.js +4 -2
  113. package/lib/cjs/utils/Evaluator.d.ts +20 -6
  114. package/lib/cjs/utils/Evaluator.js +38 -15
  115. package/lib/cjs/utils/builder.js +5 -5
  116. package/lib/cjs/utils/conditionOperators/IsEqualTo.js +3 -3
  117. package/lib/cjs/utils/formUtils.d.ts +2 -2
  118. package/lib/cjs/utils/index.d.ts +169 -2
  119. package/lib/cjs/utils/index.js +22 -2
  120. package/lib/cjs/utils/utils.d.ts +31 -45
  121. package/lib/cjs/utils/utils.js +80 -156
  122. package/lib/cjs/widgets/CalendarWidget.d.ts +1 -8
  123. package/lib/cjs/widgets/CalendarWidget.js +19 -40
  124. package/lib/mjs/Element.d.ts +2 -1
  125. package/lib/mjs/Element.js +11 -9
  126. package/lib/mjs/EventEmitter.js +2 -2
  127. package/lib/mjs/Form.js +1 -1
  128. package/lib/mjs/PDF.js +1 -1
  129. package/lib/mjs/PDFBuilder.js +1 -2
  130. package/lib/mjs/Webform.d.ts +2 -2
  131. package/lib/mjs/Webform.js +12 -13
  132. package/lib/mjs/WebformBuilder.d.ts +1 -0
  133. package/lib/mjs/WebformBuilder.js +37 -8
  134. package/lib/mjs/Wizard.d.ts +2 -2
  135. package/lib/mjs/Wizard.js +39 -25
  136. package/lib/mjs/WizardBuilder.js +1 -1
  137. package/lib/mjs/components/_classes/component/Component.d.ts +49 -15
  138. package/lib/mjs/components/_classes/component/Component.js +161 -75
  139. package/lib/mjs/components/_classes/component/editForm/Component.edit.conditional.js +1 -1
  140. package/lib/mjs/components/_classes/component/editForm/Component.edit.data.js +19 -0
  141. package/lib/mjs/components/_classes/component/editForm/Component.edit.logic.js +1 -1
  142. package/lib/mjs/components/_classes/component/editForm/utils.js +1 -1
  143. package/lib/mjs/components/_classes/componentModal/ComponentModal.js +1 -1
  144. package/lib/mjs/components/_classes/input/Input.js +1 -1
  145. package/lib/mjs/components/_classes/list/ListComponent.js +3 -3
  146. package/lib/mjs/components/_classes/nested/NestedComponent.d.ts +0 -1
  147. package/lib/mjs/components/_classes/nested/NestedComponent.form.js +13 -0
  148. package/lib/mjs/components/_classes/nested/NestedComponent.js +17 -25
  149. package/lib/mjs/components/_classes/nestedarray/NestedArrayComponent.js +1 -1
  150. package/lib/mjs/components/_classes/nesteddata/NestedDataComponent.d.ts +0 -2
  151. package/lib/mjs/components/_classes/nesteddata/NestedDataComponent.js +1 -12
  152. package/lib/mjs/components/address/Address.d.ts +9 -0
  153. package/lib/mjs/components/address/Address.js +32 -9
  154. package/lib/mjs/components/address/editForm/Address.edit.display.d.ts +4 -0
  155. package/lib/mjs/components/address/editForm/Address.edit.display.js +1 -0
  156. package/lib/mjs/components/address/editForm/Address.edit.provider.js +8 -8
  157. package/lib/mjs/components/alert/Alert.js +1 -1
  158. package/lib/mjs/components/button/Button.d.ts +1 -1
  159. package/lib/mjs/components/button/Button.js +7 -10
  160. package/lib/mjs/components/checkbox/Checkbox.js +1 -1
  161. package/lib/mjs/components/container/Container.js +1 -1
  162. package/lib/mjs/components/content/editForm/Content.edit.display.js +8 -0
  163. package/lib/mjs/components/currency/Currency.js +1 -1
  164. package/lib/mjs/components/currency/editForm/Currency.edit.display.js +12 -0
  165. package/lib/mjs/components/datagrid/DataGrid.js +5 -4
  166. package/lib/mjs/components/datamap/DataMap.js +2 -6
  167. package/lib/mjs/components/datetime/DateTime.d.ts +1 -1
  168. package/lib/mjs/components/datetime/DateTime.js +15 -13
  169. package/lib/mjs/components/datetime/editForm/DateTime.edit.validation.d.ts +66 -15
  170. package/lib/mjs/components/datetime/editForm/DateTime.edit.validation.js +68 -47
  171. package/lib/mjs/components/day/Day.js +2 -2
  172. package/lib/mjs/components/day/editForm/Day.edit.display.js +8 -0
  173. package/lib/mjs/components/editgrid/EditGrid.js +4 -13
  174. package/lib/mjs/components/editgrid/editForm/EditGrid.edit.display.js +1 -1
  175. package/lib/mjs/components/email/editForm/Email.edit.display.js +12 -0
  176. package/lib/mjs/components/fieldset/editForm/Fieldset.edit.display.js +8 -0
  177. package/lib/mjs/components/file/File.js +6 -2
  178. package/lib/mjs/components/file/editForm/File.edit.file.d.ts +13 -0
  179. package/lib/mjs/components/file/editForm/File.edit.file.js +1 -0
  180. package/lib/mjs/components/form/Form.d.ts +0 -1
  181. package/lib/mjs/components/form/Form.js +31 -24
  182. package/lib/mjs/components/form/editForm/Form.edit.form.js +3 -2
  183. package/lib/mjs/components/hidden/editForm/Hidden.edit.display.js +8 -0
  184. package/lib/mjs/components/html/HTML.js +1 -2
  185. package/lib/mjs/components/html/editForm/HTML.edit.display.js +8 -0
  186. package/lib/mjs/components/number/Number.js +1 -1
  187. package/lib/mjs/components/number/editForm/Number.edit.display.js +12 -0
  188. package/lib/mjs/components/panel/Panel.js +1 -1
  189. package/lib/mjs/components/password/editForm/Password.edit.display.js +13 -1
  190. package/lib/mjs/components/phonenumber/PhoneNumber.form.js +9 -1
  191. package/lib/mjs/components/radio/Radio.d.ts +8 -0
  192. package/lib/mjs/components/radio/Radio.js +17 -7
  193. package/lib/mjs/components/recaptcha/editForm/ReCaptcha.edit.display.js +1 -1
  194. package/lib/mjs/components/select/Select.d.ts +1 -0
  195. package/lib/mjs/components/select/Select.js +21 -5
  196. package/lib/mjs/components/select/editForm/Select.edit.data.d.ts +68 -110
  197. package/lib/mjs/components/select/editForm/Select.edit.data.js +3 -38
  198. package/lib/mjs/components/selectboxes/SelectBoxes.d.ts +6 -0
  199. package/lib/mjs/components/selectboxes/SelectBoxes.js +7 -1
  200. package/lib/mjs/components/signature/Signature.js +1 -1
  201. package/lib/mjs/components/survey/Survey.js +2 -2
  202. package/lib/mjs/components/tabs/Tabs.js +1 -0
  203. package/lib/mjs/components/tabs/editForm/Tabs.edit.display.js +8 -0
  204. package/lib/mjs/components/tags/Tags.js +1 -1
  205. package/lib/mjs/components/textarea/TextArea.js +10 -2
  206. package/lib/mjs/components/textarea/editForm/TextArea.edit.display.js +12 -0
  207. package/lib/mjs/components/textfield/TextField.js +3 -3
  208. package/lib/mjs/components/time/Time.js +1 -1
  209. package/lib/mjs/components/unknown/Unknown.form.d.ts +2 -1
  210. package/lib/mjs/components/unknown/Unknown.form.js +13 -9
  211. package/lib/mjs/components/url/editForm/Url.edit.display.js +12 -0
  212. package/lib/mjs/components/well/editForm/Well.edit.display.js +8 -0
  213. package/lib/mjs/formio.form.js +3 -3
  214. package/lib/mjs/providers/storage/uploadAdapter.js +8 -6
  215. package/lib/mjs/translations/en.d.ts +1 -234
  216. package/lib/mjs/translations/en.js +6 -47
  217. package/lib/mjs/utils/Evaluator.d.ts +20 -6
  218. package/lib/mjs/utils/Evaluator.js +31 -13
  219. package/lib/mjs/utils/builder.js +1 -1
  220. package/lib/mjs/utils/conditionOperators/IsEqualTo.js +1 -1
  221. package/lib/mjs/utils/formUtils.d.ts +2 -2
  222. package/lib/mjs/utils/index.d.ts +169 -2
  223. package/lib/mjs/utils/index.js +18 -1
  224. package/lib/mjs/utils/utils.d.ts +31 -45
  225. package/lib/mjs/utils/utils.js +72 -129
  226. package/lib/mjs/widgets/CalendarWidget.d.ts +1 -8
  227. package/lib/mjs/widgets/CalendarWidget.js +19 -40
  228. package/package.json +8 -6
  229. package/lib/cjs/i18n.d.ts +0 -13
  230. package/lib/cjs/i18n.js +0 -19
  231. package/lib/cjs/utils/i18n.d.ts +0 -19
  232. package/lib/cjs/utils/i18n.js +0 -120
  233. package/lib/mjs/i18n.d.ts +0 -13
  234. package/lib/mjs/i18n.js +0 -14
  235. package/lib/mjs/utils/i18n.d.ts +0 -19
  236. 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, isInsideScopingComponent, 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';
@@ -316,18 +316,11 @@ export default class Component extends Element {
316
316
  this._path = '';
317
317
  // Needs for Nextgen Rules Engine
318
318
  this.resetCaches();
319
- /**
320
- * Determines if this component is conditionally hidden. Should generally not be set outside of conditional logic pipeline.
321
- * This is necessary because of clearOnHide behavior that only clears when conditionally hidden - we need to track
322
- * conditionallyHidden separately from "regular" visibility.
323
- */
324
- this._parentConditionallyHidden = this.options.hasOwnProperty('parentConditionallyHidden') ? this.options.parentConditionallyHidden : false;
325
- this._conditionallyHidden = this.checkConditionallyHidden(null, data) || this._parentConditionallyHidden;
326
319
  /**
327
320
  * Determines if this component is visible, or not.
328
321
  */
329
322
  this._parentVisible = this.options.hasOwnProperty('parentVisible') ? this.options.parentVisible : true;
330
- this._visible = this._parentVisible && (this.hasCondition() ? !this._conditionallyHidden : !this.component.hidden);
323
+ this._visible = this._parentVisible && (this.hasCondition() ? !this.conditionallyHidden() : !this.component.hidden);
331
324
  this._parentDisabled = false;
332
325
  /**
333
326
  * The reference attribute name for this component
@@ -396,7 +389,7 @@ export default class Component extends Element {
396
389
  if (this.allowData && this.key) {
397
390
  this.options.name += `[${this.key}]`;
398
391
  // If component is visible or not set to clear on hide, set the default value.
399
- if (!(this.conditionallyHidden && this.component.clearOnHide)) {
392
+ if (!this.shouldConditionallyClear()) {
400
393
  if (!this.hasValue()) {
401
394
  if (this.shouldAddDefaultValue) {
402
395
  this.dataValue = this.defaultValue;
@@ -429,6 +422,45 @@ export default class Component extends Element {
429
422
  get componentsMap() {
430
423
  return this.root?.childComponentsMap || {};
431
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
+ }
440
+ parentConditionallyHidden() {
441
+ let currentParent = this.parent;
442
+ while (currentParent) {
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) {
458
+ return true;
459
+ }
460
+ currentParent = currentParent.parent;
461
+ }
462
+ return false;
463
+ }
432
464
  get data() {
433
465
  return this._data;
434
466
  }
@@ -468,8 +500,7 @@ export default class Component extends Element {
468
500
  }
469
501
  init() {
470
502
  this.disabled = this.shouldDisabled;
471
- this._conditionallyHidden = this.checkConditionallyHidden();
472
- this._visible = (this.hasCondition() ? !this.conditionallyHidden : !this.component.hidden);
503
+ this._visible = (this.hasCondition() ? !this.conditionallyHidden() : !this.component.hidden);
473
504
  if (this.component.addons?.length) {
474
505
  this.component.addons.forEach((addon) => this.createAddon(addon));
475
506
  }
@@ -635,20 +666,64 @@ export default class Component extends Element {
635
666
  }
636
667
  return this._visible && this._parentVisible;
637
668
  }
638
- get conditionallyHidden() {
639
- return this._conditionallyHidden || this._parentConditionallyHidden;
669
+ get logicallyHidden() {
670
+ if (this._logicallyHidden && !this.component.hidden) {
671
+ this._logicallyHidden = false;
672
+ }
673
+ return this._logicallyHidden;
640
674
  }
641
675
  /**
642
- * Evaluates whether the component is conditionally hidden (as opposed to intentionally hidden, e.g. via the `hidden` component schema property).
643
- * @param {object} data - The data object to evaluate the condition against.
644
- * @param {object} row - The row object to evaluate the condition against.
645
- * @returns {boolean} - Whether the component is conditionally hidden.
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.
646
678
  */
647
- checkConditionallyHidden(data = null, row = null) {
648
- if (!this.hasCondition()) {
649
- return false;
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;
650
705
  }
651
- return !this.conditionallyVisible(data, row);
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;
723
+ }
724
+ // It is conditionally hidden if its parent is conditionally hidden.
725
+ this._conditionallyHidden = this.parentConditionallyHidden();
726
+ return this._conditionallyHidden;
652
727
  }
653
728
  get currentForm() {
654
729
  return this._currentForm;
@@ -1818,7 +1893,7 @@ export default class Component extends Element {
1818
1893
  rebuild() {
1819
1894
  this.destroy();
1820
1895
  this.init();
1821
- this.visible = this.hasCondition() ? !this.conditionallyHidden : !this.component.hidden;
1896
+ this.visible = this.hasCondition() ? !this.conditionallyHidden() : !this.component.hidden;
1822
1897
  return this.redraw();
1823
1898
  }
1824
1899
  /**
@@ -1916,23 +1991,12 @@ export default class Component extends Element {
1916
1991
  if (!this.builderMode & !this.previewMode && this.fieldLogic(data, row)) {
1917
1992
  this.redraw();
1918
1993
  }
1919
- // Check advanced conditions (and cache the result)
1920
- const isConditionallyHidden = this.checkConditionallyHidden(data, row) || this._parentConditionallyHidden;
1921
- let shouldClear = false;
1922
- if (isConditionallyHidden !== this._conditionallyHidden) {
1923
- this._conditionallyHidden = isConditionallyHidden;
1924
- shouldClear = true;
1925
- }
1926
1994
  // Check visibility
1927
- const visible = (this.hasCondition() ? !this.conditionallyHidden : !this.component.hidden);
1995
+ const visible = (this.hasCondition() ? !this.conditionallyHidden() : !this.component.hidden);
1928
1996
  if (this.visible !== visible) {
1929
1997
  this.visible = visible;
1930
1998
  }
1931
- // Wait for visibility to update for nested components, so the component state is up-to-date when
1932
- // calling clearOnHide
1933
- if (shouldClear) {
1934
- this.clearOnHide();
1935
- }
1999
+ this.clearComponentOnHide();
1936
2000
  return visible;
1937
2001
  }
1938
2002
  /**
@@ -2041,9 +2105,9 @@ export default class Component extends Element {
2041
2105
  if (!_.isEqual(_.get(this.component, property), _.get(newComponent, property))) {
2042
2106
  // Advanced Logic can modify the component's hidden property; because we track conditionally hidden state
2043
2107
  // separately from the component's hidden property, and technically this Advanced Logic conditionally hides
2044
- // a component, we need to set _conditionallyHidden to the new value
2108
+ // a component, we need to set a temporary variable to the new value
2045
2109
  if (property === 'hidden') {
2046
- this._conditionallyHidden = newComponent.hidden;
2110
+ this._logicallyHidden = newComponent.hidden;
2047
2111
  }
2048
2112
  changed = true;
2049
2113
  }
@@ -2058,7 +2122,7 @@ export default class Component extends Element {
2058
2122
  component: newComponent,
2059
2123
  result,
2060
2124
  });
2061
- if (!_.isEqual(oldValue, newValue) && !(this.component.clearOnHide && this.conditionallyHidden)) {
2125
+ if (!_.isEqual(oldValue, newValue) && !this.shouldConditionallyClear()) {
2062
2126
  this.setValue(newValue);
2063
2127
  if (this.viewOnly) {
2064
2128
  this.dataValue = newValue;
@@ -2091,7 +2155,7 @@ export default class Component extends Element {
2091
2155
  component: newComponent,
2092
2156
  result,
2093
2157
  }, 'value');
2094
- if (!_.isEqual(oldValue, newValue) && !(this.component.clearOnHide && this.conditionallyHidden)) {
2158
+ if (!_.isEqual(oldValue, newValue) && !this.shouldConditionallyClear()) {
2095
2159
  this.setValue(newValue);
2096
2160
  if (this.viewOnly) {
2097
2161
  this.dataValue = newValue;
@@ -2192,17 +2256,12 @@ export default class Component extends Element {
2192
2256
  element.setAttribute('aria-invalid', invalid ? 'true' : 'false');
2193
2257
  }
2194
2258
  /**
2195
- * Clears the components data if it is conditionally hidden AND clearOnHide is set to true for this component.
2259
+ * Clear any conditionally hidden components for this component only.
2196
2260
  */
2197
- clearOnHide() {
2261
+ clearComponentOnHide() {
2198
2262
  // clearOnHide defaults to true for old forms (without the value set) so only trigger if the value is false.
2199
- if (
2200
- // if change happens inside EditGrid's row, it doesn't trigger change on the root level, so rootPristine will be true
2201
- (!this.rootPristine || this.options.server || isInsideScopingComponent(this)) &&
2202
- this.component.clearOnHide !== false &&
2203
- !this.options.readOnly &&
2204
- !this.options.showHiddenFields) {
2205
- if (this.conditionallyHidden) {
2263
+ if (this.component.clearOnHide !== false && !this.options.readOnly && !this.options.showHiddenFields) {
2264
+ if (this.shouldConditionallyClear()) {
2206
2265
  this.deleteValue();
2207
2266
  }
2208
2267
  else if (!this.hasValue() && this.shouldAddDefaultValue) {
@@ -2213,6 +2272,12 @@ export default class Component extends Element {
2213
2272
  }
2214
2273
  }
2215
2274
  }
2275
+ /**
2276
+ * Clears the components data if it is conditionally hidden AND clearOnHide is set to true for this component.
2277
+ */
2278
+ clearOnHide() {
2279
+ this.clearComponentOnHide();
2280
+ }
2216
2281
  /**
2217
2282
  * Triggers a debounced onChange event for the root component (usually Webform).
2218
2283
  * @param {...any} args - The arguments to pass to the onChange event.
@@ -2463,27 +2528,17 @@ export default class Component extends Element {
2463
2528
  * @returns {*} - The value for this component.
2464
2529
  */
2465
2530
  get dataValue() {
2466
- if (!this.key ||
2467
- (this.conditionallyHidden && this.component.clearOnHide && !this.rootPristine)) {
2468
- return this.emptyValue;
2531
+ if (!this.key) {
2532
+ return this.component.multiple ? [] : this.emptyValue;
2469
2533
  }
2470
- if (!this.hasValue() && this.shouldAddDefaultValue) {
2471
- const empty = this.component.multiple ? [] : this.emptyValue;
2472
- if (!this.rootPristine) {
2473
- this.dataValue = empty;
2474
- }
2475
- return empty;
2476
- }
2477
- return _.get(this._data, this.key);
2534
+ return _.get(this._data, this.key, this.component.multiple ? [] : this.emptyValue);
2478
2535
  }
2479
2536
  /**
2480
2537
  * Sets the static value of this component.
2481
2538
  * @param {*} value - The value to set for this component.
2482
2539
  */
2483
2540
  set dataValue(value) {
2484
- if (!this.allowData ||
2485
- !this.key ||
2486
- (this.conditionallyHidden && this.component.clearOnHide && !this.rootPristine)) {
2541
+ if (!this.allowData || !this.key) {
2487
2542
  return;
2488
2543
  }
2489
2544
  if ((value !== null) && (value !== undefined)) {
@@ -2526,13 +2581,30 @@ export default class Component extends Element {
2526
2581
  }
2527
2582
  getCustomDefaultValue(defaultValue) {
2528
2583
  if (this.component.customDefaultValue && !this.options.preview) {
2529
- defaultValue = this.evaluate(this.component.customDefaultValue, { value: '' }, 'value');
2584
+ defaultValue = this.evaluate(this.component.customDefaultValue, { value: this.dataValue }, 'value');
2530
2585
  }
2531
2586
  return defaultValue;
2532
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
+ */
2533
2601
  get shouldAddDefaultValue() {
2534
- 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);
2535
2603
  }
2604
+ /**
2605
+ * Get the default value of this component.
2606
+ * @returns {*} - The default value for this component.
2607
+ */
2536
2608
  get defaultValue() {
2537
2609
  let defaultValue = this.emptyValue;
2538
2610
  if (this.component.defaultValue) {
@@ -2610,13 +2682,16 @@ export default class Component extends Element {
2610
2682
  }
2611
2683
  const isArray = Array.isArray(value);
2612
2684
  const valueInput = this.refs.fileLink || this.refs.input;
2685
+ const isFilelink = !!this.refs.fileLink;
2613
2686
  if (isArray &&
2614
2687
  Array.isArray(this.defaultValue) &&
2615
2688
  this.refs.hasOwnProperty('input') &&
2616
2689
  valueInput &&
2617
2690
  (valueInput.length !== value.length) &&
2618
2691
  this.visible) {
2619
- this.redraw();
2692
+ if (isFilelink || valueInput.length) {
2693
+ this.redraw();
2694
+ }
2620
2695
  }
2621
2696
  if (this.isHtmlRenderMode() && flags && flags.fromSubmission && changed) {
2622
2697
  this.redraw();
@@ -2802,10 +2877,8 @@ export default class Component extends Element {
2802
2877
  }
2803
2878
  // If no calculated value or
2804
2879
  // hidden and set to clearOnHide (Don't calculate a value for a hidden field set to clear when hidden)
2805
- const { clearOnHide } = this.component;
2806
- const shouldBeCleared = this.conditionallyHidden && clearOnHide;
2807
2880
  const allowOverride = _.get(this.component, 'allowCalculateOverride', false);
2808
- if (shouldBeCleared) {
2881
+ if (this.shouldConditionallyClear()) {
2809
2882
  // remove calculated value so that the value is recalculated once component becomes visible
2810
2883
  if (this.hasOwnProperty('calculatedValue') && allowOverride) {
2811
2884
  _.unset(this, 'calculatedValue');
@@ -2926,9 +2999,11 @@ export default class Component extends Element {
2926
2999
  * @param {boolean} dirty - If the component is dirty.
2927
3000
  * @param {boolean} ignoreCondition - If conditions for the component should be ignored when checking validity.
2928
3001
  * @param {*} row - Contextual row data for this component.
3002
+ * @param {*} options - Additional options for validation.
2929
3003
  * @returns {string} - The message to show when the component is invalid.
2930
3004
  */
2931
- invalidMessage(data, dirty, ignoreCondition, row) {
3005
+ invalidMessage(data, dirty, ignoreCondition, row, options = {}) {
3006
+ const { local } = options;
2932
3007
  if (!row) {
2933
3008
  row = getContextualRowData(this.component, data, this.paths);
2934
3009
  }
@@ -2948,6 +3023,7 @@ export default class Component extends Element {
2948
3023
  component: this.component,
2949
3024
  data,
2950
3025
  row,
3026
+ local,
2951
3027
  path: this.path || this.component.key,
2952
3028
  parent: this.parent?.component,
2953
3029
  paths: this.paths,
@@ -3122,19 +3198,29 @@ export default class Component extends Element {
3122
3198
  data = data || this.rootValue;
3123
3199
  flags = flags || {};
3124
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;
3125
3212
  // Needs for Nextgen Rules Engine
3126
3213
  this.resetCaches();
3127
3214
  // Do not trigger refresh if change was triggered on blur event since components with Refresh on Blur have their own listeners
3128
3215
  if (!flags.fromBlur) {
3129
3216
  this.checkRefreshOn(flags.changes, flags);
3130
3217
  }
3131
- if (flags.noCheck) {
3132
- return true;
3133
- }
3134
3218
  this.checkComponentConditions(data, flags, row);
3135
3219
  if (this.id !== flags.triggeredComponentId) {
3136
3220
  this.calculateComponentValue(data, flags, row);
3137
3221
  }
3222
+ // We are done checking data.
3223
+ this.checkingData = false;
3138
3224
  }
3139
3225
  checkModal(errors = [], dirty = false) {
3140
3226
  const messages = errors.filter(error => !error.fromServer);
@@ -3448,7 +3534,7 @@ export default class Component extends Element {
3448
3534
  // If component definition changed, replace it.
3449
3535
  if (!_.isEqual(this.component, newComponent)) {
3450
3536
  this.component = newComponent;
3451
- const visible = this.hasCondition() ? !this.conditionallyHidden : !this.component.hidden;
3537
+ const visible = this.hasCondition() ? !this.conditionallyHidden() : !this.component.hidden;
3452
3538
  const disabled = this.shouldDisabled;
3453
3539
  // Change states which won't be recalculated during redrawing
3454
3540
  if (this.visible !== visible) {
@@ -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;
@@ -181,7 +181,6 @@ export default class NestedComponent extends Field {
181
181
  checkData(data: any, flags: any, row: any, components: any): true | undefined;
182
182
  checkConditions(data: any, flags: any, row: any): boolean;
183
183
  clearOnHide(show: any): void;
184
- restoreComponentsContext(): void;
185
184
  /**
186
185
  * Allow components to hook into the next page trigger to perform their own logic.
187
186
  * @param {Function} next - The callback to continue to the next page.
@@ -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