@formio/js 5.1.0-dev.6040.debc859 → 5.1.0-dev.6042.6e62a7a

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 (150) hide show
  1. package/Changelog.md +140 -6
  2. package/dist/formio.form.js +591 -580
  3. package/dist/formio.form.min.js +1 -1
  4. package/dist/formio.full.js +613 -602
  5. package/dist/formio.full.min.js +1 -1
  6. package/dist/formio.js +47 -14
  7. package/dist/formio.min.js +1 -1
  8. package/dist/formio.utils.js +48 -15
  9. package/dist/formio.utils.min.js +1 -1
  10. package/lib/cjs/Element.d.ts +2 -1
  11. package/lib/cjs/Element.js +6 -4
  12. package/lib/cjs/Webform.d.ts +2 -2
  13. package/lib/cjs/Webform.js +9 -9
  14. package/lib/cjs/WebformBuilder.js +5 -1
  15. package/lib/cjs/Wizard.d.ts +1 -0
  16. package/lib/cjs/Wizard.js +23 -3
  17. package/lib/cjs/components/_classes/component/Component.d.ts +50 -15
  18. package/lib/cjs/components/_classes/component/Component.js +153 -69
  19. package/lib/cjs/components/_classes/component/editForm/Component.edit.data.js +19 -0
  20. package/lib/cjs/components/_classes/component/editForm/utils.js +1 -1
  21. package/lib/cjs/components/_classes/list/ListComponent.js +2 -2
  22. package/lib/cjs/components/_classes/nested/NestedComponent.d.ts +0 -1
  23. package/lib/cjs/components/_classes/nested/NestedComponent.form.js +13 -0
  24. package/lib/cjs/components/_classes/nested/NestedComponent.js +10 -18
  25. package/lib/cjs/components/_classes/nesteddata/NestedDataComponent.d.ts +0 -2
  26. package/lib/cjs/components/_classes/nesteddata/NestedDataComponent.js +0 -11
  27. package/lib/cjs/components/address/Address.d.ts +9 -0
  28. package/lib/cjs/components/address/Address.js +31 -8
  29. package/lib/cjs/components/address/editForm/Address.edit.display.d.ts +4 -0
  30. package/lib/cjs/components/address/editForm/Address.edit.display.js +1 -0
  31. package/lib/cjs/components/address/editForm/Address.edit.provider.js +8 -8
  32. package/lib/cjs/components/content/editForm/Content.edit.display.js +8 -0
  33. package/lib/cjs/components/currency/editForm/Currency.edit.display.js +12 -0
  34. package/lib/cjs/components/datagrid/DataGrid.js +0 -3
  35. package/lib/cjs/components/datamap/DataMap.js +2 -6
  36. package/lib/cjs/components/datetime/editForm/DateTime.edit.validation.d.ts +66 -15
  37. package/lib/cjs/components/datetime/editForm/DateTime.edit.validation.js +68 -47
  38. package/lib/cjs/components/day/editForm/Day.edit.display.js +8 -0
  39. package/lib/cjs/components/editgrid/EditGrid.js +3 -13
  40. package/lib/cjs/components/email/editForm/Email.edit.display.js +12 -0
  41. package/lib/cjs/components/fieldset/editForm/Fieldset.edit.display.js +8 -0
  42. package/lib/cjs/components/file/File.js +7 -2
  43. package/lib/cjs/components/file/editForm/File.edit.file.d.ts +13 -0
  44. package/lib/cjs/components/file/editForm/File.edit.file.js +1 -0
  45. package/lib/cjs/components/form/Form.d.ts +0 -1
  46. package/lib/cjs/components/form/Form.js +18 -22
  47. package/lib/cjs/components/hidden/editForm/Hidden.edit.display.js +8 -0
  48. package/lib/cjs/components/html/HTML.js +1 -2
  49. package/lib/cjs/components/html/editForm/HTML.edit.display.js +8 -0
  50. package/lib/cjs/components/number/editForm/Number.edit.display.js +12 -0
  51. package/lib/cjs/components/password/editForm/Password.edit.display.js +13 -1
  52. package/lib/cjs/components/phonenumber/PhoneNumber.form.js +9 -1
  53. package/lib/cjs/components/radio/Radio.js +1 -1
  54. package/lib/cjs/components/select/Select.js +1 -1
  55. package/lib/cjs/components/select/editForm/Select.edit.data.d.ts +68 -110
  56. package/lib/cjs/components/select/editForm/Select.edit.data.js +2 -37
  57. package/lib/cjs/components/selectboxes/SelectBoxes.js +3 -0
  58. package/lib/cjs/components/survey/Survey.js +1 -1
  59. package/lib/cjs/components/tabs/Tabs.js +1 -0
  60. package/lib/cjs/components/tabs/editForm/Tabs.edit.display.js +8 -0
  61. package/lib/cjs/components/textarea/TextArea.js +9 -1
  62. package/lib/cjs/components/textarea/editForm/TextArea.edit.display.js +12 -0
  63. package/lib/cjs/components/textfield/TextField.js +2 -2
  64. package/lib/cjs/components/unknown/Unknown.form.d.ts +2 -1
  65. package/lib/cjs/components/unknown/Unknown.form.js +13 -9
  66. package/lib/cjs/components/url/editForm/Url.edit.display.js +12 -0
  67. package/lib/cjs/components/well/editForm/Well.edit.display.js +8 -0
  68. package/lib/cjs/formio.form.js +2 -2
  69. package/lib/cjs/providers/storage/uploadAdapter.js +5 -3
  70. package/lib/cjs/translations/en.d.ts +1 -234
  71. package/lib/cjs/translations/en.js +4 -2
  72. package/lib/cjs/utils/formUtils.d.ts +2 -2
  73. package/lib/cjs/utils/utils.d.ts +9 -8
  74. package/lib/cjs/utils/utils.js +18 -23
  75. package/lib/cjs/widgets/CalendarWidget.js +6 -1
  76. package/lib/mjs/Element.d.ts +2 -1
  77. package/lib/mjs/Element.js +6 -4
  78. package/lib/mjs/Webform.d.ts +2 -2
  79. package/lib/mjs/Webform.js +9 -9
  80. package/lib/mjs/WebformBuilder.js +5 -1
  81. package/lib/mjs/Wizard.d.ts +1 -0
  82. package/lib/mjs/Wizard.js +22 -2
  83. package/lib/mjs/components/_classes/component/Component.d.ts +50 -15
  84. package/lib/mjs/components/_classes/component/Component.js +154 -70
  85. package/lib/mjs/components/_classes/component/editForm/Component.edit.data.js +19 -0
  86. package/lib/mjs/components/_classes/component/editForm/utils.js +1 -1
  87. package/lib/mjs/components/_classes/list/ListComponent.js +2 -2
  88. package/lib/mjs/components/_classes/nested/NestedComponent.d.ts +0 -1
  89. package/lib/mjs/components/_classes/nested/NestedComponent.form.js +13 -0
  90. package/lib/mjs/components/_classes/nested/NestedComponent.js +10 -18
  91. package/lib/mjs/components/_classes/nesteddata/NestedDataComponent.d.ts +0 -2
  92. package/lib/mjs/components/_classes/nesteddata/NestedDataComponent.js +0 -11
  93. package/lib/mjs/components/address/Address.d.ts +9 -0
  94. package/lib/mjs/components/address/Address.js +31 -8
  95. package/lib/mjs/components/address/editForm/Address.edit.display.d.ts +4 -0
  96. package/lib/mjs/components/address/editForm/Address.edit.display.js +1 -0
  97. package/lib/mjs/components/address/editForm/Address.edit.provider.js +8 -8
  98. package/lib/mjs/components/content/editForm/Content.edit.display.js +8 -0
  99. package/lib/mjs/components/currency/editForm/Currency.edit.display.js +12 -0
  100. package/lib/mjs/components/datagrid/DataGrid.js +0 -3
  101. package/lib/mjs/components/datamap/DataMap.js +2 -6
  102. package/lib/mjs/components/datetime/editForm/DateTime.edit.validation.d.ts +66 -15
  103. package/lib/mjs/components/datetime/editForm/DateTime.edit.validation.js +68 -47
  104. package/lib/mjs/components/day/editForm/Day.edit.display.js +8 -0
  105. package/lib/mjs/components/editgrid/EditGrid.js +3 -12
  106. package/lib/mjs/components/email/editForm/Email.edit.display.js +12 -0
  107. package/lib/mjs/components/fieldset/editForm/Fieldset.edit.display.js +8 -0
  108. package/lib/mjs/components/file/File.js +7 -2
  109. package/lib/mjs/components/file/editForm/File.edit.file.d.ts +13 -0
  110. package/lib/mjs/components/file/editForm/File.edit.file.js +1 -0
  111. package/lib/mjs/components/form/Form.d.ts +0 -1
  112. package/lib/mjs/components/form/Form.js +18 -22
  113. package/lib/mjs/components/hidden/editForm/Hidden.edit.display.js +8 -0
  114. package/lib/mjs/components/html/HTML.js +1 -2
  115. package/lib/mjs/components/html/editForm/HTML.edit.display.js +8 -0
  116. package/lib/mjs/components/number/editForm/Number.edit.display.js +12 -0
  117. package/lib/mjs/components/password/editForm/Password.edit.display.js +13 -1
  118. package/lib/mjs/components/phonenumber/PhoneNumber.form.js +9 -1
  119. package/lib/mjs/components/radio/Radio.js +1 -1
  120. package/lib/mjs/components/select/Select.js +1 -1
  121. package/lib/mjs/components/select/editForm/Select.edit.data.d.ts +68 -110
  122. package/lib/mjs/components/select/editForm/Select.edit.data.js +2 -37
  123. package/lib/mjs/components/selectboxes/SelectBoxes.js +3 -0
  124. package/lib/mjs/components/survey/Survey.js +1 -1
  125. package/lib/mjs/components/tabs/Tabs.js +1 -0
  126. package/lib/mjs/components/tabs/editForm/Tabs.edit.display.js +8 -0
  127. package/lib/mjs/components/textarea/TextArea.js +9 -1
  128. package/lib/mjs/components/textarea/editForm/TextArea.edit.display.js +12 -0
  129. package/lib/mjs/components/textfield/TextField.js +2 -2
  130. package/lib/mjs/components/unknown/Unknown.form.d.ts +2 -1
  131. package/lib/mjs/components/unknown/Unknown.form.js +13 -9
  132. package/lib/mjs/components/url/editForm/Url.edit.display.js +12 -0
  133. package/lib/mjs/components/well/editForm/Well.edit.display.js +8 -0
  134. package/lib/mjs/formio.form.js +1 -1
  135. package/lib/mjs/providers/storage/uploadAdapter.js +5 -3
  136. package/lib/mjs/translations/en.d.ts +1 -234
  137. package/lib/mjs/translations/en.js +5 -47
  138. package/lib/mjs/utils/formUtils.d.ts +2 -2
  139. package/lib/mjs/utils/utils.d.ts +9 -8
  140. package/lib/mjs/utils/utils.js +16 -21
  141. package/lib/mjs/widgets/CalendarWidget.js +7 -2
  142. package/package.json +2 -2
  143. package/lib/cjs/i18n.d.ts +0 -13
  144. package/lib/cjs/i18n.js +0 -19
  145. package/lib/cjs/utils/i18n.d.ts +0 -19
  146. package/lib/cjs/utils/i18n.js +0 -120
  147. package/lib/mjs/i18n.d.ts +0 -13
  148. package/lib/mjs/i18n.js +0 -14
  149. package/lib/mjs/utils/i18n.d.ts +0 -19
  150. package/lib/mjs/utils/i18n.js +0 -112
@@ -6,7 +6,7 @@ import isMobile from 'ismobilejs';
6
6
  import { processOne, processOneSync, validateProcessInfo } from '@formio/core/process';
7
7
  import { Formio } from '../../../Formio';
8
8
  import * as FormioUtils from '../../../utils/utils';
9
- import { fastCloneDeep, boolValue, isInsideScopingComponent, currentTimezone, getScriptPlugin, getContextualRowData } from '../../../utils/utils';
9
+ import { fastCloneDeep, boolValue, currentTimezone, getScriptPlugin, getContextualRowData } from '../../../utils/utils';
10
10
  import Element from '../../../Element';
11
11
  import ComponentModal from '../componentModal/ComponentModal';
12
12
  import Widgets from '../../../widgets';
@@ -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,46 @@ 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
+ *
428
+ * @returns {boolean} - If the parent should conditionally clear.
429
+ */
430
+ parentShouldConditionallyClear() {
431
+ let currentParent = this.parent;
432
+ while (currentParent) {
433
+ if ((currentParent.allowData && currentParent._conditionallyClear) ||
434
+ (!currentParent.allowData && currentParent._conditionallyHidden)) {
435
+ return true;
436
+ }
437
+ currentParent = currentParent.parent;
438
+ }
439
+ return false;
440
+ }
441
+ parentConditionallyHidden() {
442
+ let currentParent = this.parent;
443
+ while (currentParent) {
444
+ if (currentParent._conditionallyHidden) {
445
+ return true;
446
+ }
447
+ currentParent = currentParent.parent;
448
+ }
449
+ return false;
450
+ }
451
+ /**
452
+ * Returns true if any of the parents default their component "hidden" property to true.
453
+ * @returns {boolean} - If any parent defaults the hidden property to true.
454
+ */
455
+ anyParentDefaultsHidden() {
456
+ let currentParent = this.parent;
457
+ while (currentParent) {
458
+ if (currentParent.component.hidden) {
459
+ return true;
460
+ }
461
+ currentParent = currentParent.parent;
462
+ }
463
+ return false;
464
+ }
432
465
  get data() {
433
466
  return this._data;
434
467
  }
@@ -468,8 +501,7 @@ export default class Component extends Element {
468
501
  }
469
502
  init() {
470
503
  this.disabled = this.shouldDisabled;
471
- this._conditionallyHidden = this.checkConditionallyHidden();
472
- this._visible = (this.hasCondition() ? !this.conditionallyHidden : !this.component.hidden);
504
+ this._visible = (this.hasCondition() ? !this.conditionallyHidden() : !this.component.hidden);
473
505
  if (this.component.addons?.length) {
474
506
  this.component.addons.forEach((addon) => this.createAddon(addon));
475
507
  }
@@ -635,20 +667,64 @@ export default class Component extends Element {
635
667
  }
636
668
  return this._visible && this._parentVisible;
637
669
  }
638
- get conditionallyHidden() {
639
- return this._conditionallyHidden || this._parentConditionallyHidden;
670
+ get logicallyHidden() {
671
+ if (this._logicallyHidden && !this.component.hidden) {
672
+ this._logicallyHidden = false;
673
+ }
674
+ return this._logicallyHidden;
640
675
  }
641
676
  /**
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.
677
+ * Determines if the component should clear its value when the root form is pristine.
678
+ * @returns {boolean} - If the component should clear its value when the root form is pristine.
646
679
  */
647
- checkConditionallyHidden(data = null, row = null) {
648
- if (!this.hasCondition()) {
649
- return false;
680
+ shouldConditionallyClearOnPristine() {
681
+ // If the form is pristine, we should NOT clear the value of a conditionally hidden child component
682
+ // of a layout component that defaults to hidden using the "hidden" component property.
683
+ return !this.anyParentDefaultsHidden();
684
+ }
685
+ /**
686
+ * Returns if the component should clear its value when conditionally hidden.
687
+ * @returns {boolean} - If the component should clear its value when conditionally hidden.
688
+ */
689
+ shouldConditionallyClear() {
690
+ // Skip if this component has clearOnHide set to false.
691
+ if (this.component.clearOnHide === false) {
692
+ this._conditionallyClear = false;
693
+ return this._conditionallyClear;
650
694
  }
651
- return !this.conditionallyVisible(data, row);
695
+ // If the component is logically hidden, then it is conditionally hidden and should clear.
696
+ if (this.logicallyHidden) {
697
+ this._conditionallyClear = true;
698
+ return this._conditionallyClear;
699
+ }
700
+ // If we have a condition and it is not conditionally visible, the it should conditionally clear.
701
+ if (this.hasCondition() &&
702
+ !this.conditionallyVisible() &&
703
+ (!this.rootPristine || this.shouldConditionallyClearOnPristine())) {
704
+ this._conditionallyClear = true;
705
+ return this._conditionallyClear;
706
+ }
707
+ this._conditionallyClear = this.hasSetValue ? false : this.parentShouldConditionallyClear();
708
+ return this._conditionallyClear;
709
+ }
710
+ /**
711
+ * Returns if the component is conditionally hidden.
712
+ * @returns {boolean} - If the component is conditionally hidden.
713
+ */
714
+ conditionallyHidden() {
715
+ // If it is logically hidden, then it is conditionally hidden.
716
+ if (this.logicallyHidden) {
717
+ this._conditionallyHidden = true;
718
+ return this._conditionallyHidden;
719
+ }
720
+ // If it has a condition, and is not conditionally visible, then it is conditionally hidden.
721
+ if (this.hasCondition() && !this.conditionallyVisible()) {
722
+ this._conditionallyHidden = true;
723
+ return this._conditionallyHidden;
724
+ }
725
+ // It is conditionally hidden if its parent is conditionally hidden.
726
+ this._conditionallyHidden = this.parentConditionallyHidden();
727
+ return this._conditionallyHidden;
652
728
  }
653
729
  get currentForm() {
654
730
  return this._currentForm;
@@ -1818,7 +1894,7 @@ export default class Component extends Element {
1818
1894
  rebuild() {
1819
1895
  this.destroy();
1820
1896
  this.init();
1821
- this.visible = this.hasCondition() ? !this.conditionallyHidden : !this.component.hidden;
1897
+ this.visible = this.hasCondition() ? !this.conditionallyHidden() : !this.component.hidden;
1822
1898
  return this.redraw();
1823
1899
  }
1824
1900
  /**
@@ -1916,23 +1992,12 @@ export default class Component extends Element {
1916
1992
  if (!this.builderMode & !this.previewMode && this.fieldLogic(data, row)) {
1917
1993
  this.redraw();
1918
1994
  }
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
1995
  // Check visibility
1927
- const visible = (this.hasCondition() ? !this.conditionallyHidden : !this.component.hidden);
1996
+ const visible = (this.hasCondition() ? !this.conditionallyHidden() : !this.component.hidden);
1928
1997
  if (this.visible !== visible) {
1929
1998
  this.visible = visible;
1930
1999
  }
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
- }
2000
+ this.clearComponentOnHide();
1936
2001
  return visible;
1937
2002
  }
1938
2003
  /**
@@ -2041,9 +2106,9 @@ export default class Component extends Element {
2041
2106
  if (!_.isEqual(_.get(this.component, property), _.get(newComponent, property))) {
2042
2107
  // Advanced Logic can modify the component's hidden property; because we track conditionally hidden state
2043
2108
  // 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
2109
+ // a component, we need to set a temporary variable to the new value
2045
2110
  if (property === 'hidden') {
2046
- this._conditionallyHidden = newComponent.hidden;
2111
+ this._logicallyHidden = newComponent.hidden;
2047
2112
  }
2048
2113
  changed = true;
2049
2114
  }
@@ -2058,7 +2123,7 @@ export default class Component extends Element {
2058
2123
  component: newComponent,
2059
2124
  result,
2060
2125
  });
2061
- if (!_.isEqual(oldValue, newValue) && !(this.component.clearOnHide && this.conditionallyHidden)) {
2126
+ if (!_.isEqual(oldValue, newValue) && !this.shouldConditionallyClear()) {
2062
2127
  this.setValue(newValue);
2063
2128
  if (this.viewOnly) {
2064
2129
  this.dataValue = newValue;
@@ -2091,7 +2156,7 @@ export default class Component extends Element {
2091
2156
  component: newComponent,
2092
2157
  result,
2093
2158
  }, 'value');
2094
- if (!_.isEqual(oldValue, newValue) && !(this.component.clearOnHide && this.conditionallyHidden)) {
2159
+ if (!_.isEqual(oldValue, newValue) && !this.shouldConditionallyClear()) {
2095
2160
  this.setValue(newValue);
2096
2161
  if (this.viewOnly) {
2097
2162
  this.dataValue = newValue;
@@ -2192,17 +2257,12 @@ export default class Component extends Element {
2192
2257
  element.setAttribute('aria-invalid', invalid ? 'true' : 'false');
2193
2258
  }
2194
2259
  /**
2195
- * Clears the components data if it is conditionally hidden AND clearOnHide is set to true for this component.
2260
+ * Clear any conditionally hidden components for this component only.
2196
2261
  */
2197
- clearOnHide() {
2262
+ clearComponentOnHide() {
2198
2263
  // 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) {
2264
+ if (this.component.clearOnHide !== false && !this.options.readOnly && !this.options.showHiddenFields) {
2265
+ if (this.shouldConditionallyClear()) {
2206
2266
  this.deleteValue();
2207
2267
  }
2208
2268
  else if (!this.hasValue() && this.shouldAddDefaultValue) {
@@ -2213,6 +2273,12 @@ export default class Component extends Element {
2213
2273
  }
2214
2274
  }
2215
2275
  }
2276
+ /**
2277
+ * Clears the components data if it is conditionally hidden AND clearOnHide is set to true for this component.
2278
+ */
2279
+ clearOnHide() {
2280
+ this.clearComponentOnHide();
2281
+ }
2216
2282
  /**
2217
2283
  * Triggers a debounced onChange event for the root component (usually Webform).
2218
2284
  * @param {...any} args - The arguments to pass to the onChange event.
@@ -2463,27 +2529,17 @@ export default class Component extends Element {
2463
2529
  * @returns {*} - The value for this component.
2464
2530
  */
2465
2531
  get dataValue() {
2466
- if (!this.key ||
2467
- (this.conditionallyHidden && this.component.clearOnHide && !this.rootPristine)) {
2468
- return this.emptyValue;
2469
- }
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;
2532
+ if (!this.key) {
2533
+ return this.component.multiple ? [] : this.emptyValue;
2476
2534
  }
2477
- return _.get(this._data, this.key);
2535
+ return _.get(this._data, this.key, this.component.multiple ? [] : this.emptyValue);
2478
2536
  }
2479
2537
  /**
2480
2538
  * Sets the static value of this component.
2481
2539
  * @param {*} value - The value to set for this component.
2482
2540
  */
2483
2541
  set dataValue(value) {
2484
- if (!this.allowData ||
2485
- !this.key ||
2486
- (this.conditionallyHidden && this.component.clearOnHide && !this.rootPristine)) {
2542
+ if (!this.allowData || !this.key) {
2487
2543
  return;
2488
2544
  }
2489
2545
  if ((value !== null) && (value !== undefined)) {
@@ -2526,13 +2582,30 @@ export default class Component extends Element {
2526
2582
  }
2527
2583
  getCustomDefaultValue(defaultValue) {
2528
2584
  if (this.component.customDefaultValue && !this.options.preview) {
2529
- defaultValue = this.evaluate(this.component.customDefaultValue, { value: '' }, 'value');
2585
+ defaultValue = this.evaluate(this.component.customDefaultValue, { value: this.dataValue }, 'value');
2530
2586
  }
2531
2587
  return defaultValue;
2532
2588
  }
2589
+ /**
2590
+ * Returns if a component has a default value set.
2591
+ * @returns {boolean} - TRUE if a default value is set.
2592
+ */
2593
+ get hasDefaultValue() {
2594
+ return this.component.customDefaultValue || (this.component.hasOwnProperty('defaultValue') &&
2595
+ (this.component.defaultValue !== null) &&
2596
+ (this.component.defaultValue !== undefined));
2597
+ }
2598
+ /**
2599
+ * Determine if we should add a default value for this component.
2600
+ * @returns {boolean} - TRUE if a default value should be set
2601
+ */
2533
2602
  get shouldAddDefaultValue() {
2534
- return !this.options.noDefaults || (this.component.defaultValue && !this.isEmpty(this.component.defaultValue)) || this.component.customDefaultValue;
2603
+ return this.pristine && this.allowData && (this.hasDefaultValue || !this.options.noDefaults);
2535
2604
  }
2605
+ /**
2606
+ * Get the default value of this component.
2607
+ * @returns {*} - The default value for this component.
2608
+ */
2536
2609
  get defaultValue() {
2537
2610
  let defaultValue = this.emptyValue;
2538
2611
  if (this.component.defaultValue) {
@@ -2802,10 +2875,8 @@ export default class Component extends Element {
2802
2875
  }
2803
2876
  // If no calculated value or
2804
2877
  // 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
2878
  const allowOverride = _.get(this.component, 'allowCalculateOverride', false);
2808
- if (shouldBeCleared) {
2879
+ if (this.shouldConditionallyClear()) {
2809
2880
  // remove calculated value so that the value is recalculated once component becomes visible
2810
2881
  if (this.hasOwnProperty('calculatedValue') && allowOverride) {
2811
2882
  _.unset(this, 'calculatedValue');
@@ -2926,9 +2997,11 @@ export default class Component extends Element {
2926
2997
  * @param {boolean} dirty - If the component is dirty.
2927
2998
  * @param {boolean} ignoreCondition - If conditions for the component should be ignored when checking validity.
2928
2999
  * @param {*} row - Contextual row data for this component.
3000
+ * @param {*} options - Additional options for validation.
2929
3001
  * @returns {string} - The message to show when the component is invalid.
2930
3002
  */
2931
- invalidMessage(data, dirty, ignoreCondition, row) {
3003
+ invalidMessage(data, dirty, ignoreCondition, row, options = {}) {
3004
+ const { local } = options;
2932
3005
  if (!row) {
2933
3006
  row = getContextualRowData(this.component, data, this.paths);
2934
3007
  }
@@ -2948,6 +3021,7 @@ export default class Component extends Element {
2948
3021
  component: this.component,
2949
3022
  data,
2950
3023
  row,
3024
+ local,
2951
3025
  path: this.path || this.component.key,
2952
3026
  parent: this.parent?.component,
2953
3027
  paths: this.paths,
@@ -3122,6 +3196,14 @@ export default class Component extends Element {
3122
3196
  data = data || this.rootValue;
3123
3197
  flags = flags || {};
3124
3198
  row = row || this.data;
3199
+ // Some components (for legacy reasons) have calls to "checkData" in inappropriate places such
3200
+ // as setValue. Historically, this was bypassed by a series of cached states around the data model
3201
+ // which caused its own problems. We need to ensure that premium and custom components do not fall into
3202
+ // an infinite loop by only checking this component once.
3203
+ if (this.checkingData) {
3204
+ return;
3205
+ }
3206
+ this.checkingData = true;
3125
3207
  // Needs for Nextgen Rules Engine
3126
3208
  this.resetCaches();
3127
3209
  // Do not trigger refresh if change was triggered on blur event since components with Refresh on Blur have their own listeners
@@ -3135,6 +3217,8 @@ export default class Component extends Element {
3135
3217
  if (this.id !== flags.triggeredComponentId) {
3136
3218
  this.calculateComponentValue(data, flags, row);
3137
3219
  }
3220
+ // We are done checking data.
3221
+ this.checkingData = false;
3138
3222
  }
3139
3223
  checkModal(errors = [], dirty = false) {
3140
3224
  const messages = errors.filter(error => !error.fromServer);
@@ -3448,7 +3532,7 @@ export default class Component extends Element {
3448
3532
  // If component definition changed, replace it.
3449
3533
  if (!_.isEqual(this.component, newComponent)) {
3450
3534
  this.component = newComponent;
3451
- const visible = this.hasCondition() ? !this.conditionallyHidden : !this.component.hidden;
3535
+ const visible = this.hasCondition() ? !this.conditionallyHidden() : !this.component.hidden;
3452
3536
  const disabled = this.shouldDisabled;
3453
3537
  // Change states which won't be recalculated during redrawing
3454
3538
  if (this.visible !== visible) {
@@ -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: {
@@ -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) {
@@ -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
@@ -81,18 +81,15 @@ export default class NestedComponent extends Field {
81
81
  const visibilityChanged = this._visible !== value;
82
82
  this._visible = value;
83
83
  const isVisible = this.visible;
84
- const isConditionallyHidden = this.checkConditionallyHidden();
85
84
  const forceShow = this.shouldForceShow();
86
85
  const forceHide = this.shouldForceHide();
87
86
  this.components.forEach((component) => {
88
87
  // Set the parent visibility first since we may have nested components within nested components
89
88
  // and they need to be able to determine their visibility based on the parent visibility.
90
89
  component.parentVisible = isVisible;
91
- component._parentConditionallyHidden = isConditionallyHidden;
92
90
  let visible;
93
91
  if (component.hasCondition()) {
94
- component._conditionallyHidden = component.checkConditionallyHidden() || component._parentConditionallyHidden;
95
- visible = !component.conditionallyHidden;
92
+ visible = !component.conditionallyHidden();
96
93
  }
97
94
  else {
98
95
  visible = !component.component.hidden;
@@ -373,7 +370,6 @@ export default class NestedComponent extends Field {
373
370
  data = data || this.data;
374
371
  options.parent = this;
375
372
  options.parentVisible = this.visible;
376
- options.parentConditionallyHidden = this.conditionallyHidden;
377
373
  options.root = options?.root || this.root || this;
378
374
  options.localRoot = this.localRoot;
379
375
  options.skipInit = true;
@@ -631,19 +627,8 @@ export default class NestedComponent extends Field {
631
627
  }
632
628
  clearOnHide(show) {
633
629
  super.clearOnHide(show);
634
- if (this.component.clearOnHide) {
635
- if (this.allowData && !this.hasValue() && !this.conditionallyHidden) {
636
- this.dataValue = this.defaultValue;
637
- }
638
- if (this.hasValue()) {
639
- this.restoreComponentsContext();
640
- }
641
- }
642
630
  this.getComponents().forEach(component => component.clearOnHide(show));
643
631
  }
644
- restoreComponentsContext() {
645
- this.getComponents().forEach((component) => component.data = this.dataValue);
646
- }
647
632
  /**
648
633
  * Allow components to hook into the next page trigger to perform their own logic.
649
634
  * @param {Function} next - The callback to continue to the next page.
@@ -661,7 +646,7 @@ export default class NestedComponent extends Field {
661
646
  }
662
647
  calculateValue(data, flags, row) {
663
648
  // Do not iterate into children and calculateValues if this nested component is conditionally hidden.
664
- if (this.conditionallyHidden) {
649
+ if (this.conditionallyHidden()) {
665
650
  return false;
666
651
  }
667
652
  return this.getComponents().reduce((changed, comp) => comp.calculateValue(data, flags, row) || changed, super.calculateValue(data, flags, row));
@@ -831,7 +816,7 @@ export default class NestedComponent extends Field {
831
816
  else if (value && component.hasValue(value)) {
832
817
  return component.setValue(_.get(value, component.key), flags);
833
818
  }
834
- else if ((!this.rootPristine || component.visible) && component.shouldAddDefaultValue) {
819
+ else if ((!this.rootPristine || component.visible) && (flags.resetValue || component.shouldAddDefaultValue)) {
835
820
  flags.noValidate = !flags.dirty;
836
821
  flags.resetValue = true;
837
822
  return component.setValue(component.defaultValue, flags);
@@ -841,6 +826,13 @@ export default class NestedComponent extends Field {
841
826
  if (!value) {
842
827
  return false;
843
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
+ }
844
836
  return this.getComponents().reduce((changed, component) => {
845
837
  return this.setNestedValue(component, value, flags, changed) || changed;
846
838
  }, false);
@@ -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.
@@ -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.
@@ -36,12 +36,21 @@ export default class AddressComponent extends ContainerComponent {
36
36
  get autocompleteMode(): boolean;
37
37
  get manualMode(): boolean;
38
38
  get manualModeEnabled(): boolean;
39
+ restoreComponentsContext(): void;
39
40
  get isMultiple(): boolean;
40
41
  set address(value: any);
41
42
  get address(): any;
42
43
  isValueInLegacyFormat(value: any): any;
43
44
  normalizeValue(value: any): any;
44
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
+ };
45
54
  get removeValueIcon(): any;
46
55
  get searchInput(): any;
47
56
  get addRowButton(): any;