@formio/js 5.1.0-dev.6050.f1c0fbe → 5.1.0-dev.6054.7ae1465

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 (30) hide show
  1. package/Changelog.md +140 -6
  2. package/dist/formio.form.js +6 -6
  3. package/dist/formio.form.min.js +1 -1
  4. package/dist/formio.full.js +8 -8
  5. package/dist/formio.full.min.js +1 -1
  6. package/lib/cjs/components/_classes/component/Component.d.ts +7 -11
  7. package/lib/cjs/components/_classes/component/Component.js +28 -26
  8. package/lib/cjs/components/_classes/nested/NestedComponent.js +8 -1
  9. package/lib/cjs/components/_classes/nesteddata/NestedDataComponent.d.ts +0 -2
  10. package/lib/cjs/components/_classes/nesteddata/NestedDataComponent.js +0 -11
  11. package/lib/cjs/components/address/Address.d.ts +0 -8
  12. package/lib/cjs/components/address/Address.js +8 -18
  13. package/lib/cjs/components/address/editForm/Address.edit.provider.js +8 -8
  14. package/lib/cjs/components/file/editForm/File.edit.file.d.ts +13 -0
  15. package/lib/cjs/components/file/editForm/File.edit.file.js +1 -0
  16. package/lib/cjs/components/form/Form.js +4 -0
  17. package/lib/cjs/components/selectboxes/SelectBoxes.js +3 -0
  18. package/lib/mjs/components/_classes/component/Component.d.ts +7 -11
  19. package/lib/mjs/components/_classes/component/Component.js +28 -26
  20. package/lib/mjs/components/_classes/nested/NestedComponent.js +8 -1
  21. package/lib/mjs/components/_classes/nesteddata/NestedDataComponent.d.ts +0 -2
  22. package/lib/mjs/components/_classes/nesteddata/NestedDataComponent.js +0 -11
  23. package/lib/mjs/components/address/Address.d.ts +0 -8
  24. package/lib/mjs/components/address/Address.js +8 -18
  25. package/lib/mjs/components/address/editForm/Address.edit.provider.js +8 -8
  26. package/lib/mjs/components/file/editForm/File.edit.file.d.ts +13 -0
  27. package/lib/mjs/components/file/editForm/File.edit.file.js +1 -0
  28. package/lib/mjs/components/form/Form.js +4 -0
  29. package/lib/mjs/components/selectboxes/SelectBoxes.js +3 -0
  30. package/package.json +1 -1
@@ -129,16 +129,6 @@ declare class Component extends Element {
129
129
  * The reference attribute name for this component
130
130
  */
131
131
  _referenceAttributeName: string;
132
- /**
133
- * Sometimes the customDefaultValue does not set the "value" within the script, but is just a script to execute. This
134
- * flag is used to determine if the customDefaultValue should be used to set the value of the component or not based on
135
- * if there is a "value=" within the script.
136
- */
137
- shouldSetCustomDefault: any;
138
- /**
139
- * Same as customDefaultValue, but for calculateValue.
140
- */
141
- shouldSetCalculatedValue: any;
142
132
  triggerChange: (...args: any[]) => any;
143
133
  /**
144
134
  * Used to trigger a redraw event within this component.
@@ -896,7 +886,12 @@ declare class Component extends Element {
896
886
  */
897
887
  deleteValue(): void;
898
888
  getCustomDefaultValue(defaultValue: any): any;
899
- get shouldAddDefaultValue(): any;
889
+ /**
890
+ * Returns if a component has a default value set.
891
+ * @returns {boolean} - TRUE if a default value is set.
892
+ */
893
+ get hasDefaultValue(): boolean;
894
+ get shouldAddDefaultValue(): boolean;
900
895
  get defaultValue(): any;
901
896
  /**
902
897
  * Get the input value of this component.
@@ -1070,6 +1065,7 @@ declare class Component extends Element {
1070
1065
  * @returns {void|boolean} - TRUE if no check should be performed on the component.
1071
1066
  */
1072
1067
  checkData(data?: any, flags?: any, row?: any): void | boolean;
1068
+ checkingData: boolean | undefined;
1073
1069
  checkModal(errors?: any[], dirty?: boolean): void;
1074
1070
  get validationValue(): any;
1075
1071
  isEmpty(value?: any): any;
@@ -361,22 +361,6 @@ class Component extends Element_1.default {
361
361
  * The reference attribute name for this component
362
362
  */
363
363
  this._referenceAttributeName = 'ref';
364
- /**
365
- * Sometimes the customDefaultValue does not set the "value" within the script, but is just a script to execute. This
366
- * flag is used to determine if the customDefaultValue should be used to set the value of the component or not based on
367
- * if there is a "value=" within the script.
368
- */
369
- this.shouldSetCustomDefault = true;
370
- if (this.component.customDefaultValue && (typeof this.component.customDefaultValue === 'string')) {
371
- this.shouldSetCustomDefault = this.component.customDefaultValue.match(/value\s*=/);
372
- }
373
- /**
374
- * Same as customDefaultValue, but for calculateValue.
375
- */
376
- this.shouldSetCalculatedValue = true;
377
- if (this.component.calculateValue && (typeof this.component.calculateValue === 'string')) {
378
- this.shouldSetCalculatedValue = this.component.calculateValue.match(/value\s*=/);
379
- }
380
364
  /**
381
365
  * Used to trigger a new change in this component.
382
366
  * @type {Function} - Call to trigger a change in this component.
@@ -2552,15 +2536,27 @@ class Component extends Element_1.default {
2552
2536
  }
2553
2537
  getCustomDefaultValue(defaultValue) {
2554
2538
  if (this.component.customDefaultValue && !this.options.preview) {
2555
- const customDefaultValue = this.evaluate(this.component.customDefaultValue, { value: '' }, 'value');
2556
- if (this.shouldSetCustomDefault) {
2557
- defaultValue = customDefaultValue;
2558
- }
2539
+ defaultValue = this.evaluate(this.component.customDefaultValue, { value: this.dataValue }, 'value');
2559
2540
  }
2560
2541
  return defaultValue;
2561
2542
  }
2543
+ /**
2544
+ * Returns if a component has a default value set.
2545
+ * @returns {boolean} - TRUE if a default value is set.
2546
+ */
2547
+ get hasDefaultValue() {
2548
+ return this.component.customDefaultValue || (this.component.hasOwnProperty('defaultValue') &&
2549
+ (this.component.defaultValue !== null) &&
2550
+ (this.component.defaultValue !== undefined));
2551
+ }
2562
2552
  get shouldAddDefaultValue() {
2563
- return !this.options.noDefaults || (this.component.defaultValue && !this.isEmpty(this.component.defaultValue)) || this.component.customDefaultValue;
2553
+ // It should add a default value if...
2554
+ // 1.) Ensure they have not set "noDefaults". If that is true, then will always return false. AND
2555
+ // 2.) The component is pristine (user has not manually modified it). AND
2556
+ // 3.) There is a default value setting present and it is not NULL or UNDEFINED.
2557
+ return !this.options.noDefaults && this.pristine && (this.hasDefaultValue ||
2558
+ // Empty strings and booleans are allowed primitives whose defaults are automatically added.
2559
+ (this.emptyValue === '' || (typeof this.emptyValue === 'boolean')));
2564
2560
  }
2565
2561
  get defaultValue() {
2566
2562
  let defaultValue = this.emptyValue;
@@ -2815,7 +2811,7 @@ class Component extends Element_1.default {
2815
2811
  }
2816
2812
  doValueCalculation(dataValue, data, row) {
2817
2813
  var _a;
2818
- const calculatedValue = this.evaluate(this.component.calculateValue, {
2814
+ return this.evaluate(this.component.calculateValue, {
2819
2815
  value: dataValue,
2820
2816
  data,
2821
2817
  row: row || this.data,
@@ -2823,10 +2819,6 @@ class Component extends Element_1.default {
2823
2819
  data: this.rootValue
2824
2820
  }
2825
2821
  }, 'value');
2826
- if (this.shouldSetCalculatedValue) {
2827
- return calculatedValue;
2828
- }
2829
- return dataValue;
2830
2822
  }
2831
2823
  /* eslint-disable max-statements */
2832
2824
  calculateComponentValue(data, flags, row) {
@@ -3159,6 +3151,14 @@ class Component extends Element_1.default {
3159
3151
  data = data || this.rootValue;
3160
3152
  flags = flags || {};
3161
3153
  row = row || this.data;
3154
+ // Some components (for legacy reasons) have calls to "checkData" in inappropriate places such
3155
+ // as setValue. Historically, this was bypassed by a series of cached states around the data model
3156
+ // which caused its own problems. We need to ensure that premium and custom components do not fall into
3157
+ // an infinite loop by only checking this component once.
3158
+ if (this.checkingData) {
3159
+ return;
3160
+ }
3161
+ this.checkingData = true;
3162
3162
  // Needs for Nextgen Rules Engine
3163
3163
  this.resetCaches();
3164
3164
  // Do not trigger refresh if change was triggered on blur event since components with Refresh on Blur have their own listeners
@@ -3172,6 +3172,8 @@ class Component extends Element_1.default {
3172
3172
  if (this.id !== flags.triggeredComponentId) {
3173
3173
  this.calculateComponentValue(data, flags, row);
3174
3174
  }
3175
+ // We are done checking data.
3176
+ this.checkingData = false;
3175
3177
  }
3176
3178
  checkModal(errors = [], dirty = false) {
3177
3179
  const messages = errors.filter(error => !error.fromServer);
@@ -821,7 +821,7 @@ class NestedComponent extends Field_1.default {
821
821
  else if (value && component.hasValue(value)) {
822
822
  return component.setValue(lodash_1.default.get(value, component.key), flags);
823
823
  }
824
- else if ((!this.rootPristine || component.visible) && component.shouldAddDefaultValue) {
824
+ else if ((!this.rootPristine || component.visible) && (flags.resetValue || component.shouldAddDefaultValue)) {
825
825
  flags.noValidate = !flags.dirty;
826
826
  flags.resetValue = true;
827
827
  return component.setValue(component.defaultValue, flags);
@@ -831,6 +831,13 @@ class NestedComponent extends Field_1.default {
831
831
  if (!value) {
832
832
  return false;
833
833
  }
834
+ // If the value is equal to the empty value, then this means we need to reset the values.
835
+ if (lodash_1.default.isEqual(value, this.emptyValue)) {
836
+ // TO-DO: For a future major release, we need to investigate removing the need for the
837
+ // "resetValue" flag. This seems like a hack that is no longer necessary and the renderer
838
+ // may behave more deterministically without it.
839
+ flags.resetValue = true;
840
+ }
834
841
  return this.getComponents().reduce((changed, component) => {
835
842
  return this.setNestedValue(component, value, flags, changed) || changed;
836
843
  }, 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.
@@ -88,17 +88,6 @@ class NestedDataComponent extends NestedComponent_1.default {
88
88
  `);
89
89
  return result;
90
90
  }
91
- everyComponent(fn, options = {}) {
92
- if (options === null || options === void 0 ? void 0 : options.email) {
93
- if (options.fromRoot) {
94
- delete options.fromRoot;
95
- }
96
- else {
97
- return;
98
- }
99
- }
100
- return super.everyComponent(fn, options);
101
- }
102
91
  /**
103
92
  * Get the value of this component.
104
93
  * @returns {any} - Return the value of this component.
@@ -43,14 +43,6 @@ 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
- };
54
46
  get removeValueIcon(): any;
55
47
  get searchInput(): any;
56
48
  get addRowButton(): any;
@@ -26,6 +26,7 @@ class AddressComponent extends Container_1.default {
26
26
  key: 'address',
27
27
  switchToManualModeLabel: 'Can\'t find address? Switch to manual mode.',
28
28
  provider: '',
29
+ providerOptions: {},
29
30
  manualModeViewString: '',
30
31
  hideLabel: false,
31
32
  disableClearIcon: false,
@@ -115,20 +116,20 @@ class AddressComponent extends Container_1.default {
115
116
  NestedComponent_1.default.prototype.addComponents.call(this, this.manualMode ? this.address : {});
116
117
  }
117
118
  Field_1.default.prototype.init.call(this);
118
- let provider = this.component.provider;
119
- const providerOptions = this.providerOptions;
120
- const map = this.component.map;
121
119
  if (!this.builderMode) {
122
- if (provider) {
120
+ if (this.component.provider) {
121
+ const { provider, providerOptions, } = this.component;
123
122
  if (lodash_1.default.get(providerOptions, 'params.subscriptionKey')) {
124
123
  lodash_1.default.set(providerOptions, "params['subscription-key']", lodash_1.default.get(providerOptions, 'params.subscriptionKey'));
125
124
  lodash_1.default.unset(providerOptions, 'params.subscriptionKey');
126
125
  }
127
126
  this.provider = this.initializeProvider(provider, providerOptions);
128
127
  }
129
- else if (map) {
128
+ else if (this.component.map) {
130
129
  // Fallback to legacy version where Google Maps was the only provider.
131
- provider = this.component.provider = GoogleAddressProvider_1.GoogleAddressProvider.name;
130
+ this.component.provider = GoogleAddressProvider_1.GoogleAddressProvider.name;
131
+ this.component.providerOptions = this.component.providerOptions || {};
132
+ const { map, provider, providerOptions, } = this.component;
132
133
  const { key, region, } = map;
133
134
  if (key) {
134
135
  lodash_1.default.set(providerOptions, 'params.key', key);
@@ -261,16 +262,6 @@ class AddressComponent extends Container_1.default {
261
262
  ? (this.refs[AddressComponent.modeSwitcherRef] || null)
262
263
  : null;
263
264
  }
264
- get providerOptions() {
265
- return {
266
- params: Object.assign({ subscriptionKey: this.component.subscriptionKey, key: this.component.apiKey }, this.component.params),
267
- url: this.component.url,
268
- queryProperty: this.component.queryProperty,
269
- responseProperty: this.component.responseProperty,
270
- displayValueProperty: this.component.displayValueProperty,
271
- autocompleteOptions: this.component.autocompleteOptions
272
- };
273
- }
274
265
  get removeValueIcon() {
275
266
  return this.refs
276
267
  ? (this.refs[AddressComponent.removeValueIconRef] || null)
@@ -384,8 +375,7 @@ class AddressComponent extends Container_1.default {
384
375
  const result = ((this.builderMode || this.manualMode) ? super.attach : Field_1.default.prototype.attach).call(this, element);
385
376
  if (!this.builderMode) {
386
377
  if (!this.provider && this.component.provider) {
387
- const provider = this.component.provider;
388
- const providerOptions = this.providerOptions;
378
+ const { provider, providerOptions, } = this.component;
389
379
  this.provider = this.initializeProvider(provider, providerOptions);
390
380
  }
391
381
  }
@@ -31,7 +31,7 @@ exports.default = [
31
31
  {
32
32
  type: 'textfield',
33
33
  input: true,
34
- key: "subscriptionKey",
34
+ key: "providerOptions.params.subscriptionKey",
35
35
  label: 'Subscription Key',
36
36
  placeholder: 'Enter Subscription Key',
37
37
  weight: 10,
@@ -46,7 +46,7 @@ exports.default = [
46
46
  {
47
47
  type: 'textfield',
48
48
  input: true,
49
- key: 'url',
49
+ key: 'providerOptions.url',
50
50
  label: 'Url',
51
51
  placeholder: 'Enter Url',
52
52
  weight: 10,
@@ -61,7 +61,7 @@ exports.default = [
61
61
  {
62
62
  type: 'textfield',
63
63
  input: true,
64
- key: 'queryProperty',
64
+ key: 'providerOptions.queryProperty',
65
65
  label: 'Query Property',
66
66
  defaultValue: 'query',
67
67
  placeholder: 'Enter Query Property',
@@ -74,7 +74,7 @@ exports.default = [
74
74
  {
75
75
  type: 'textfield',
76
76
  input: true,
77
- key: 'responseProperty',
77
+ key: 'providerOptions.responseProperty',
78
78
  label: 'Response Property',
79
79
  placeholder: 'Enter Response Property',
80
80
  weight: 30,
@@ -86,7 +86,7 @@ exports.default = [
86
86
  {
87
87
  type: 'textfield',
88
88
  input: true,
89
- key: 'displayValueProperty',
89
+ key: 'providerOptions.displayValueProperty',
90
90
  label: 'Display Value Property',
91
91
  placeholder: 'Display Value Property',
92
92
  weight: 40,
@@ -98,7 +98,7 @@ exports.default = [
98
98
  {
99
99
  type: 'textarea',
100
100
  input: true,
101
- key: 'params',
101
+ key: 'providerOptions.params',
102
102
  label: 'Params',
103
103
  placeholder: '{ ... }',
104
104
  weight: 50,
@@ -113,7 +113,7 @@ exports.default = [
113
113
  {
114
114
  type: 'textfield',
115
115
  input: true,
116
- key: 'apiKey',
116
+ key: 'providerOptions.params.key',
117
117
  label: 'API Key',
118
118
  placeholder: 'Enter API Key',
119
119
  weight: 10,
@@ -128,7 +128,7 @@ exports.default = [
128
128
  {
129
129
  type: 'textarea',
130
130
  input: true,
131
- key: 'autocompleteOptions',
131
+ key: 'providerOptions.params.autocompleteOptions',
132
132
  label: 'Provider options',
133
133
  placeholder: 'Enter provider options as JSON object',
134
134
  defaultValue: {},
@@ -16,6 +16,7 @@ declare const _default: ({
16
16
  components?: undefined;
17
17
  rows?: undefined;
18
18
  editor?: undefined;
19
+ as?: undefined;
19
20
  optionsLabelPosition?: undefined;
20
21
  inline?: undefined;
21
22
  defaultValue?: undefined;
@@ -45,6 +46,7 @@ declare const _default: ({
45
46
  components?: undefined;
46
47
  rows?: undefined;
47
48
  editor?: undefined;
49
+ as?: undefined;
48
50
  optionsLabelPosition?: undefined;
49
51
  inline?: undefined;
50
52
  defaultValue?: undefined;
@@ -91,6 +93,7 @@ declare const _default: ({
91
93
  data?: undefined;
92
94
  rows?: undefined;
93
95
  editor?: undefined;
96
+ as?: undefined;
94
97
  optionsLabelPosition?: undefined;
95
98
  inline?: undefined;
96
99
  defaultValue?: undefined;
@@ -120,6 +123,7 @@ declare const _default: ({
120
123
  components?: undefined;
121
124
  rows?: undefined;
122
125
  editor?: undefined;
126
+ as?: undefined;
123
127
  optionsLabelPosition?: undefined;
124
128
  inline?: undefined;
125
129
  defaultValue?: undefined;
@@ -149,6 +153,7 @@ declare const _default: ({
149
153
  components?: undefined;
150
154
  rows?: undefined;
151
155
  editor?: undefined;
156
+ as?: undefined;
152
157
  optionsLabelPosition?: undefined;
153
158
  inline?: undefined;
154
159
  defaultValue?: undefined;
@@ -160,6 +165,7 @@ declare const _default: ({
160
165
  tooltip: string;
161
166
  rows: number;
162
167
  editor: string;
168
+ as: string;
163
169
  input: boolean;
164
170
  weight: number;
165
171
  placeholder: string;
@@ -207,6 +213,7 @@ declare const _default: ({
207
213
  components?: undefined;
208
214
  rows?: undefined;
209
215
  editor?: undefined;
216
+ as?: undefined;
210
217
  optionsLabelPosition?: undefined;
211
218
  inline?: undefined;
212
219
  defaultValue?: undefined;
@@ -227,6 +234,7 @@ declare const _default: ({
227
234
  components?: undefined;
228
235
  rows?: undefined;
229
236
  editor?: undefined;
237
+ as?: undefined;
230
238
  optionsLabelPosition?: undefined;
231
239
  inline?: undefined;
232
240
  defaultValue?: undefined;
@@ -247,6 +255,7 @@ declare const _default: ({
247
255
  components?: undefined;
248
256
  rows?: undefined;
249
257
  editor?: undefined;
258
+ as?: undefined;
250
259
  optionsLabelPosition?: undefined;
251
260
  inline?: undefined;
252
261
  defaultValue?: undefined;
@@ -276,6 +285,7 @@ declare const _default: ({
276
285
  components?: undefined;
277
286
  rows?: undefined;
278
287
  editor?: undefined;
288
+ as?: undefined;
279
289
  optionsLabelPosition?: undefined;
280
290
  inline?: undefined;
281
291
  defaultValue?: undefined;
@@ -305,6 +315,7 @@ declare const _default: ({
305
315
  components?: undefined;
306
316
  rows?: undefined;
307
317
  editor?: undefined;
318
+ as?: undefined;
308
319
  optionsLabelPosition?: undefined;
309
320
  inline?: undefined;
310
321
  defaultValue?: undefined;
@@ -332,6 +343,7 @@ declare const _default: ({
332
343
  components?: undefined;
333
344
  rows?: undefined;
334
345
  editor?: undefined;
346
+ as?: undefined;
335
347
  } | {
336
348
  type: string;
337
349
  input: boolean;
@@ -353,6 +365,7 @@ declare const _default: ({
353
365
  tableView?: undefined;
354
366
  rows?: undefined;
355
367
  editor?: undefined;
368
+ as?: undefined;
356
369
  optionsLabelPosition?: undefined;
357
370
  inline?: undefined;
358
371
  defaultValue?: undefined;
@@ -120,6 +120,7 @@ exports.default = [
120
120
  tooltip: 'Pass your custom xhr options(optional)',
121
121
  rows: 5,
122
122
  editor: 'ace',
123
+ as: 'json',
123
124
  input: true,
124
125
  weight: 15,
125
126
  placeholder: `{
@@ -115,6 +115,10 @@ class FormComponent extends Component_1.default {
115
115
  get emptyValue() {
116
116
  return { data: {} };
117
117
  }
118
+ // In order for the subform values to set properly, we must always say that nested forms have a default value.
119
+ get hasDefaultValue() {
120
+ return true;
121
+ }
118
122
  get ready() {
119
123
  return this.subFormReady || Promise.resolve();
120
124
  }
@@ -64,6 +64,9 @@ class SelectBoxesComponent extends Radio_1.default {
64
64
  info.attr.class = 'form-check-input';
65
65
  return info;
66
66
  }
67
+ get hasDefaultValue() {
68
+ return true;
69
+ }
67
70
  get emptyValue() {
68
71
  return this.component.values.reduce((prev, value) => {
69
72
  if (value.value) {
@@ -129,16 +129,6 @@ declare class Component extends Element {
129
129
  * The reference attribute name for this component
130
130
  */
131
131
  _referenceAttributeName: string;
132
- /**
133
- * Sometimes the customDefaultValue does not set the "value" within the script, but is just a script to execute. This
134
- * flag is used to determine if the customDefaultValue should be used to set the value of the component or not based on
135
- * if there is a "value=" within the script.
136
- */
137
- shouldSetCustomDefault: any;
138
- /**
139
- * Same as customDefaultValue, but for calculateValue.
140
- */
141
- shouldSetCalculatedValue: any;
142
132
  triggerChange: (...args: any[]) => any;
143
133
  /**
144
134
  * Used to trigger a redraw event within this component.
@@ -896,7 +886,12 @@ declare class Component extends Element {
896
886
  */
897
887
  deleteValue(): void;
898
888
  getCustomDefaultValue(defaultValue: any): any;
899
- get shouldAddDefaultValue(): any;
889
+ /**
890
+ * Returns if a component has a default value set.
891
+ * @returns {boolean} - TRUE if a default value is set.
892
+ */
893
+ get hasDefaultValue(): boolean;
894
+ get shouldAddDefaultValue(): boolean;
900
895
  get defaultValue(): any;
901
896
  /**
902
897
  * Get the input value of this component.
@@ -1070,6 +1065,7 @@ declare class Component extends Element {
1070
1065
  * @returns {void|boolean} - TRUE if no check should be performed on the component.
1071
1066
  */
1072
1067
  checkData(data?: any, flags?: any, row?: any): void | boolean;
1068
+ checkingData: boolean | undefined;
1073
1069
  checkModal(errors?: any[], dirty?: boolean): void;
1074
1070
  get validationValue(): any;
1075
1071
  isEmpty(value?: any): any;
@@ -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.
@@ -2521,15 +2505,27 @@ export default class Component extends Element {
2521
2505
  }
2522
2506
  getCustomDefaultValue(defaultValue) {
2523
2507
  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
- }
2508
+ defaultValue = this.evaluate(this.component.customDefaultValue, { value: this.dataValue }, 'value');
2528
2509
  }
2529
2510
  return defaultValue;
2530
2511
  }
2512
+ /**
2513
+ * Returns if a component has a default value set.
2514
+ * @returns {boolean} - TRUE if a default value is set.
2515
+ */
2516
+ get hasDefaultValue() {
2517
+ return this.component.customDefaultValue || (this.component.hasOwnProperty('defaultValue') &&
2518
+ (this.component.defaultValue !== null) &&
2519
+ (this.component.defaultValue !== undefined));
2520
+ }
2531
2521
  get shouldAddDefaultValue() {
2532
- return !this.options.noDefaults || (this.component.defaultValue && !this.isEmpty(this.component.defaultValue)) || this.component.customDefaultValue;
2522
+ // It should add a default value if...
2523
+ // 1.) Ensure they have not set "noDefaults". If that is true, then will always return false. AND
2524
+ // 2.) The component is pristine (user has not manually modified it). AND
2525
+ // 3.) There is a default value setting present and it is not NULL or UNDEFINED.
2526
+ return !this.options.noDefaults && this.pristine && (this.hasDefaultValue ||
2527
+ // Empty strings and booleans are allowed primitives whose defaults are automatically added.
2528
+ (this.emptyValue === '' || (typeof this.emptyValue === 'boolean')));
2533
2529
  }
2534
2530
  get defaultValue() {
2535
2531
  let defaultValue = this.emptyValue;
@@ -2783,7 +2779,7 @@ export default class Component extends Element {
2783
2779
  return value;
2784
2780
  }
2785
2781
  doValueCalculation(dataValue, data, row) {
2786
- const calculatedValue = this.evaluate(this.component.calculateValue, {
2782
+ return this.evaluate(this.component.calculateValue, {
2787
2783
  value: dataValue,
2788
2784
  data,
2789
2785
  row: row || this.data,
@@ -2791,10 +2787,6 @@ export default class Component extends Element {
2791
2787
  data: this.rootValue
2792
2788
  }
2793
2789
  }, 'value');
2794
- if (this.shouldSetCalculatedValue) {
2795
- return calculatedValue;
2796
- }
2797
- return dataValue;
2798
2790
  }
2799
2791
  /* eslint-disable max-statements */
2800
2792
  calculateComponentValue(data, flags, row) {
@@ -3124,6 +3116,14 @@ export default class Component extends Element {
3124
3116
  data = data || this.rootValue;
3125
3117
  flags = flags || {};
3126
3118
  row = row || this.data;
3119
+ // Some components (for legacy reasons) have calls to "checkData" in inappropriate places such
3120
+ // as setValue. Historically, this was bypassed by a series of cached states around the data model
3121
+ // which caused its own problems. We need to ensure that premium and custom components do not fall into
3122
+ // an infinite loop by only checking this component once.
3123
+ if (this.checkingData) {
3124
+ return;
3125
+ }
3126
+ this.checkingData = true;
3127
3127
  // Needs for Nextgen Rules Engine
3128
3128
  this.resetCaches();
3129
3129
  // Do not trigger refresh if change was triggered on blur event since components with Refresh on Blur have their own listeners
@@ -3137,6 +3137,8 @@ export default class Component extends Element {
3137
3137
  if (this.id !== flags.triggeredComponentId) {
3138
3138
  this.calculateComponentValue(data, flags, row);
3139
3139
  }
3140
+ // We are done checking data.
3141
+ this.checkingData = false;
3140
3142
  }
3141
3143
  checkModal(errors = [], dirty = false) {
3142
3144
  const messages = errors.filter(error => !error.fromServer);
@@ -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);
@@ -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.