@formio/js 5.0.0-dev.5822.ae2ec5b → 5.0.0-dev.5826.02fa4d9

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.
@@ -1253,7 +1253,7 @@ class Webform extends NestedDataComponent_1.default {
1253
1253
  const errors = shouldValidate
1254
1254
  ? this.validate(value.data, Object.assign(Object.assign({}, flags), { noValidate: false, process: 'change' }))
1255
1255
  : [];
1256
- value.isValid = errors.length === 0;
1256
+ value.isValid = (errors || []).filter(err => !err.fromServer).length === 0;
1257
1257
  this.loading = false;
1258
1258
  if (this.submitted) {
1259
1259
  // show server errors while they are not cleaned/fixed
@@ -914,8 +914,11 @@ class WebformBuilder extends Component_1.default {
914
914
  keyboardActionsEnabled = keyboardActionsEnabled === 'true';
915
915
  }
916
916
  this.keyboardActionsEnabled = keyboardActionsEnabled;
917
+ const isSubmitButton = (comp) => {
918
+ return (comp.type === 'button') && ((comp.action === 'submit') || !comp.action);
919
+ };
917
920
  const isShowSubmitButton = !this.options.noDefaultSubmitButton
918
- && (!form.components.length || !form.components.find(comp => comp.key === 'submit'));
921
+ && (!form.components.length || !form.components.find(comp => isSubmitButton(comp)));
919
922
  // Ensure there is at least a submit button.
920
923
  if (isShowSubmitButton) {
921
924
  form.components.push({
@@ -1,6 +1,7 @@
1
1
  export default class ListComponent extends Field {
2
2
  get isSelectURL(): boolean;
3
3
  get selectData(): any;
4
+ get dataReady(): any;
4
5
  get shouldLoad(): boolean;
5
6
  getTemplateKeys(): void;
6
7
  templateKeys: string[] | undefined;
@@ -10,6 +11,9 @@ export default class ListComponent extends Field {
10
11
  loadItems(): void;
11
12
  getOptionTemplate(data: any, value: any, index: any): any;
12
13
  itemTemplate(data: any, value: any, index: any): any;
14
+ set itemsLoaded(promise: any);
15
+ get itemsLoaded(): any;
16
+ _itemsLoaded: any;
13
17
  handleLoadingError(err: any): void;
14
18
  loading: boolean | undefined;
15
19
  networkError: boolean | undefined;
@@ -26,6 +26,16 @@ class ListComponent extends Field_1.default {
26
26
  const selectData = lodash_1.default.get(this.root, 'submission.metadata.selectData', {});
27
27
  return lodash_1.default.get(selectData, this.path);
28
28
  }
29
+ get dataReady() {
30
+ // If the root submission has been set, and we are still not attached, then assume
31
+ // that our data is ready.
32
+ if (this.root &&
33
+ this.root.submissionSet &&
34
+ !this.attached) {
35
+ return Promise.resolve();
36
+ }
37
+ return this.itemsLoaded;
38
+ }
29
39
  get shouldLoad() {
30
40
  if (this.loadingError) {
31
41
  return false;
@@ -112,6 +122,12 @@ class ListComponent extends Field_1.default {
112
122
  return this.sanitize(JSON.stringify(data), this.shouldSanitizeValue);
113
123
  }
114
124
  }
125
+ get itemsLoaded() {
126
+ return this._itemsLoaded || Promise.resolve();
127
+ }
128
+ set itemsLoaded(promise) {
129
+ this._itemsLoaded = promise;
130
+ }
115
131
  handleLoadingError(err) {
116
132
  this.loading = false;
117
133
  if (err.networkError) {
@@ -683,9 +683,12 @@ class NestedComponent extends Field_1.default {
683
683
  return this.getComponents().reduce((valid, comp) => comp.isValid(data, dirty) && valid, super.isValid(data, dirty));
684
684
  }
685
685
  validationProcessor({ scope, data, row, instance, component }, flags) {
686
+ var _a;
686
687
  const { dirty } = flags;
687
688
  if (this.root.hasExtraPages && this.page !== this.root.page) {
688
- instance = this.getComponent(component.path);
689
+ instance = ((_a = this.childComponentsMap) === null || _a === void 0 ? void 0 : _a.hasOwnProperty(component.path))
690
+ ? this.childComponentsMap[component.path]
691
+ : this.getComponent(component.path);
689
692
  }
690
693
  if (!instance) {
691
694
  return;
@@ -420,7 +420,9 @@ class DayComponent extends Field_1.default {
420
420
  DAY = null;
421
421
  }
422
422
  if (!this.showMonth) {
423
- DAY = DAY === 0 ? 0 : DAY - 1;
423
+ if (!lodash_1.default.isNull(DAY)) {
424
+ DAY = DAY === 0 ? 0 : DAY - 1;
425
+ }
424
426
  YEAR = YEAR - 1;
425
427
  MONTH = null;
426
428
  }
@@ -23,10 +23,10 @@ export default class RadioComponent extends ListComponent {
23
23
  get listData(): any;
24
24
  templateData: {} | undefined;
25
25
  triggerUpdate: ((...args: any[]) => any) | undefined;
26
- itemsLoaded: Promise<any> | undefined;
27
26
  itemsLoadedResolve: ((value: any) => void) | undefined;
28
27
  optionsLoaded: boolean | undefined;
29
28
  loadedOptions: any[] | undefined;
29
+ beforeSubmit(): Promise<any>;
30
30
  render(): import("../_classes/field/Field").default;
31
31
  attach(element: any): Promise<void>;
32
32
  detach(element: any): void;
@@ -126,12 +126,23 @@ class RadioComponent extends ListComponent_1.default {
126
126
  this.itemsLoaded = new Promise((resolve) => {
127
127
  this.itemsLoadedResolve = resolve;
128
128
  });
129
- this.optionsLoaded = false;
129
+ this.optionsLoaded = !this.component.dataSrc || this.component.dataSrc === 'values';
130
130
  this.loadedOptions = [];
131
+ if (!this.visible) {
132
+ this.itemsLoadedResolve();
133
+ }
131
134
  // Get the template keys for this radio component.
132
135
  this.getTemplateKeys();
133
136
  }
137
+ beforeSubmit() {
138
+ return new Promise(res => {
139
+ this.dataReady.then(() => res(true));
140
+ });
141
+ }
134
142
  render() {
143
+ if (!this.optionsLoaded) {
144
+ return super.render(this.renderTemplate('loader'));
145
+ }
135
146
  return super.render(this.renderTemplate('radio', {
136
147
  input: this.inputInfo,
137
148
  inline: this.component.inline,
@@ -242,12 +253,22 @@ class RadioComponent extends ListComponent_1.default {
242
253
  this.refs.input[index].checked = (inputValue === value.toString());
243
254
  }
244
255
  }
256
+ get shouldLoad() {
257
+ // do not load options if the value is empty in readOnly and we have options available in metadata
258
+ if (this.options.readOnly && this.isEmpty() && this.listData) {
259
+ return false;
260
+ }
261
+ return super.shouldLoad;
262
+ }
245
263
  loadItems(url, search, headers, options, method, body) {
246
264
  if (this.optionsLoaded) {
265
+ this.itemsLoadedResolve();
247
266
  return;
248
267
  }
249
268
  if (!this.shouldLoad && this.listData) {
250
269
  this.loadItemsFromMetadata();
270
+ this.itemsLoadedResolve();
271
+ this.optionsLoaded = true;
251
272
  return;
252
273
  }
253
274
  // Ensure we have a method and remove any body if method is get
@@ -278,6 +299,7 @@ class RadioComponent extends ListComponent_1.default {
278
299
  this.redraw();
279
300
  })
280
301
  .catch((err) => {
302
+ this.optionsLoaded = true;
281
303
  this.handleLoadingError(err);
282
304
  });
283
305
  }
@@ -318,6 +340,7 @@ class RadioComponent extends ListComponent_1.default {
318
340
  }
319
341
  lodash_1.default.set(submission.metadata.listData, this.path, listData);
320
342
  }
343
+ this.itemsLoadedResolve();
321
344
  }
322
345
  setSelectedClasses() {
323
346
  if (this.refs.wrapper) {
@@ -54,8 +54,6 @@ export default class SelectComponent extends ListComponent {
54
54
  static savedValueTypes(schema: any): any[];
55
55
  templateData: {} | undefined;
56
56
  triggerUpdate: ((...args: any[]) => any) | undefined;
57
- set itemsLoaded(promise: any);
58
- get itemsLoaded(): any;
59
57
  itemsLoadedResolve: ((value: any) => void) | undefined;
60
58
  isFromSearch: boolean | undefined;
61
59
  searchServerCount: any;
@@ -65,7 +63,6 @@ export default class SelectComponent extends ListComponent {
65
63
  defaultDownloadedResources: any;
66
64
  activated: boolean | undefined;
67
65
  shouldPositionDropdown: any;
68
- get dataReady(): any;
69
66
  get emptyValue(): {};
70
67
  get valueProperty(): any;
71
68
  get inputInfo(): any;
@@ -141,7 +138,6 @@ export default class SelectComponent extends ListComponent {
141
138
  lazyLoadInit: boolean | undefined;
142
139
  isInitApiCallNeeded(hasValue: any): any;
143
140
  setChoicesValue(value: any, hasPreviousValue: any, flags?: {}): void;
144
- _itemsLoaded: any;
145
141
  validateValueAvailability(setting: any, value: any): boolean;
146
142
  /**
147
143
  * Performs required transformations on the initial value to use in selectOptions
@@ -150,16 +150,6 @@ class SelectComponent extends ListComponent_1.default {
150
150
  // Get the template keys for this select component.
151
151
  this.getTemplateKeys();
152
152
  }
153
- get dataReady() {
154
- // If the root submission has been set, and we are still not attached, then assume
155
- // that our data is ready.
156
- if (this.root &&
157
- this.root.submissionSet &&
158
- !this.attached) {
159
- return Promise.resolve();
160
- }
161
- return this.itemsLoaded;
162
- }
163
153
  get defaultSchema() {
164
154
  return SelectComponent.schema();
165
155
  }
@@ -1369,12 +1359,6 @@ class SelectComponent extends ListComponent_1.default {
1369
1359
  }
1370
1360
  }
1371
1361
  }
1372
- get itemsLoaded() {
1373
- return this._itemsLoaded || Promise.resolve();
1374
- }
1375
- set itemsLoaded(promise) {
1376
- this._itemsLoaded = promise;
1377
- }
1378
1362
  validateValueAvailability(setting, value) {
1379
1363
  if (!(0, utils_1.boolValue)(setting) || !value) {
1380
1364
  return true;
@@ -1259,7 +1259,7 @@ export default class Webform extends NestedDataComponent {
1259
1259
  process: 'change'
1260
1260
  })
1261
1261
  : [];
1262
- value.isValid = errors.length === 0;
1262
+ value.isValid = (errors || []).filter(err => !err.fromServer).length === 0;
1263
1263
  this.loading = false;
1264
1264
  if (this.submitted) {
1265
1265
  // show server errors while they are not cleaned/fixed
@@ -898,8 +898,11 @@ export default class WebformBuilder extends Component {
898
898
  keyboardActionsEnabled = keyboardActionsEnabled === 'true';
899
899
  }
900
900
  this.keyboardActionsEnabled = keyboardActionsEnabled;
901
+ const isSubmitButton = (comp) => {
902
+ return (comp.type === 'button') && ((comp.action === 'submit') || !comp.action);
903
+ };
901
904
  const isShowSubmitButton = !this.options.noDefaultSubmitButton
902
- && (!form.components.length || !form.components.find(comp => comp.key === 'submit'));
905
+ && (!form.components.length || !form.components.find(comp => isSubmitButton(comp)));
903
906
  // Ensure there is at least a submit button.
904
907
  if (isShowSubmitButton) {
905
908
  form.components.push({
@@ -1,6 +1,7 @@
1
1
  export default class ListComponent extends Field {
2
2
  get isSelectURL(): boolean;
3
3
  get selectData(): any;
4
+ get dataReady(): any;
4
5
  get shouldLoad(): boolean;
5
6
  getTemplateKeys(): void;
6
7
  templateKeys: string[] | undefined;
@@ -10,6 +11,9 @@ export default class ListComponent extends Field {
10
11
  loadItems(): void;
11
12
  getOptionTemplate(data: any, value: any, index: any): any;
12
13
  itemTemplate(data: any, value: any, index: any): any;
14
+ set itemsLoaded(promise: any);
15
+ get itemsLoaded(): any;
16
+ _itemsLoaded: any;
13
17
  handleLoadingError(err: any): void;
14
18
  loading: boolean | undefined;
15
19
  networkError: boolean | undefined;
@@ -21,6 +21,16 @@ export default class ListComponent extends Field {
21
21
  const selectData = _.get(this.root, 'submission.metadata.selectData', {});
22
22
  return _.get(selectData, this.path);
23
23
  }
24
+ get dataReady() {
25
+ // If the root submission has been set, and we are still not attached, then assume
26
+ // that our data is ready.
27
+ if (this.root &&
28
+ this.root.submissionSet &&
29
+ !this.attached) {
30
+ return Promise.resolve();
31
+ }
32
+ return this.itemsLoaded;
33
+ }
24
34
  get shouldLoad() {
25
35
  if (this.loadingError) {
26
36
  return false;
@@ -107,6 +117,12 @@ export default class ListComponent extends Field {
107
117
  return this.sanitize(JSON.stringify(data), this.shouldSanitizeValue);
108
118
  }
109
119
  }
120
+ get itemsLoaded() {
121
+ return this._itemsLoaded || Promise.resolve();
122
+ }
123
+ set itemsLoaded(promise) {
124
+ this._itemsLoaded = promise;
125
+ }
110
126
  handleLoadingError(err) {
111
127
  this.loading = false;
112
128
  if (err.networkError) {
@@ -681,7 +681,9 @@ export default class NestedComponent extends Field {
681
681
  validationProcessor({ scope, data, row, instance, component }, flags) {
682
682
  const { dirty } = flags;
683
683
  if (this.root.hasExtraPages && this.page !== this.root.page) {
684
- instance = this.getComponent(component.path);
684
+ instance = this.childComponentsMap?.hasOwnProperty(component.path)
685
+ ? this.childComponentsMap[component.path]
686
+ : this.getComponent(component.path);
685
687
  }
686
688
  if (!instance) {
687
689
  return;
@@ -418,7 +418,9 @@ export default class DayComponent extends Field {
418
418
  DAY = null;
419
419
  }
420
420
  if (!this.showMonth) {
421
- DAY = DAY === 0 ? 0 : DAY - 1;
421
+ if (!_.isNull(DAY)) {
422
+ DAY = DAY === 0 ? 0 : DAY - 1;
423
+ }
422
424
  YEAR = YEAR - 1;
423
425
  MONTH = null;
424
426
  }
@@ -23,10 +23,10 @@ export default class RadioComponent extends ListComponent {
23
23
  get listData(): any;
24
24
  templateData: {} | undefined;
25
25
  triggerUpdate: ((...args: any[]) => any) | undefined;
26
- itemsLoaded: Promise<any> | undefined;
27
26
  itemsLoadedResolve: ((value: any) => void) | undefined;
28
27
  optionsLoaded: boolean | undefined;
29
28
  loadedOptions: any[] | undefined;
29
+ beforeSubmit(): Promise<any>;
30
30
  render(): import("../_classes/field/Field").default;
31
31
  attach(element: any): Promise<void>;
32
32
  detach(element: any): void;
@@ -126,12 +126,23 @@ export default class RadioComponent extends ListComponent {
126
126
  this.itemsLoaded = new Promise((resolve) => {
127
127
  this.itemsLoadedResolve = resolve;
128
128
  });
129
- this.optionsLoaded = false;
129
+ this.optionsLoaded = !this.component.dataSrc || this.component.dataSrc === 'values';
130
130
  this.loadedOptions = [];
131
+ if (!this.visible) {
132
+ this.itemsLoadedResolve();
133
+ }
131
134
  // Get the template keys for this radio component.
132
135
  this.getTemplateKeys();
133
136
  }
137
+ beforeSubmit() {
138
+ return new Promise(res => {
139
+ this.dataReady.then(() => res(true));
140
+ });
141
+ }
134
142
  render() {
143
+ if (!this.optionsLoaded) {
144
+ return super.render(this.renderTemplate('loader'));
145
+ }
135
146
  return super.render(this.renderTemplate('radio', {
136
147
  input: this.inputInfo,
137
148
  inline: this.component.inline,
@@ -242,12 +253,22 @@ export default class RadioComponent extends ListComponent {
242
253
  this.refs.input[index].checked = (inputValue === value.toString());
243
254
  }
244
255
  }
256
+ get shouldLoad() {
257
+ // do not load options if the value is empty in readOnly and we have options available in metadata
258
+ if (this.options.readOnly && this.isEmpty() && this.listData) {
259
+ return false;
260
+ }
261
+ return super.shouldLoad;
262
+ }
245
263
  loadItems(url, search, headers, options, method, body) {
246
264
  if (this.optionsLoaded) {
265
+ this.itemsLoadedResolve();
247
266
  return;
248
267
  }
249
268
  if (!this.shouldLoad && this.listData) {
250
269
  this.loadItemsFromMetadata();
270
+ this.itemsLoadedResolve();
271
+ this.optionsLoaded = true;
251
272
  return;
252
273
  }
253
274
  // Ensure we have a method and remove any body if method is get
@@ -278,6 +299,7 @@ export default class RadioComponent extends ListComponent {
278
299
  this.redraw();
279
300
  })
280
301
  .catch((err) => {
302
+ this.optionsLoaded = true;
281
303
  this.handleLoadingError(err);
282
304
  });
283
305
  }
@@ -318,6 +340,7 @@ export default class RadioComponent extends ListComponent {
318
340
  }
319
341
  _.set(submission.metadata.listData, this.path, listData);
320
342
  }
343
+ this.itemsLoadedResolve();
321
344
  }
322
345
  setSelectedClasses() {
323
346
  if (this.refs.wrapper) {
@@ -54,8 +54,6 @@ export default class SelectComponent extends ListComponent {
54
54
  static savedValueTypes(schema: any): any[];
55
55
  templateData: {} | undefined;
56
56
  triggerUpdate: ((...args: any[]) => any) | undefined;
57
- set itemsLoaded(promise: any);
58
- get itemsLoaded(): any;
59
57
  itemsLoadedResolve: ((value: any) => void) | undefined;
60
58
  isFromSearch: boolean | undefined;
61
59
  searchServerCount: any;
@@ -65,7 +63,6 @@ export default class SelectComponent extends ListComponent {
65
63
  defaultDownloadedResources: any;
66
64
  activated: boolean | undefined;
67
65
  shouldPositionDropdown: any;
68
- get dataReady(): any;
69
66
  get emptyValue(): {};
70
67
  get valueProperty(): any;
71
68
  get inputInfo(): any;
@@ -141,7 +138,6 @@ export default class SelectComponent extends ListComponent {
141
138
  lazyLoadInit: boolean | undefined;
142
139
  isInitApiCallNeeded(hasValue: any): any;
143
140
  setChoicesValue(value: any, hasPreviousValue: any, flags?: {}): void;
144
- _itemsLoaded: any;
145
141
  validateValueAvailability(setting: any, value: any): boolean;
146
142
  /**
147
143
  * Performs required transformations on the initial value to use in selectOptions
@@ -150,16 +150,6 @@ export default class SelectComponent extends ListComponent {
150
150
  // Get the template keys for this select component.
151
151
  this.getTemplateKeys();
152
152
  }
153
- get dataReady() {
154
- // If the root submission has been set, and we are still not attached, then assume
155
- // that our data is ready.
156
- if (this.root &&
157
- this.root.submissionSet &&
158
- !this.attached) {
159
- return Promise.resolve();
160
- }
161
- return this.itemsLoaded;
162
- }
163
153
  get defaultSchema() {
164
154
  return SelectComponent.schema();
165
155
  }
@@ -1397,12 +1387,6 @@ export default class SelectComponent extends ListComponent {
1397
1387
  }
1398
1388
  }
1399
1389
  }
1400
- get itemsLoaded() {
1401
- return this._itemsLoaded || Promise.resolve();
1402
- }
1403
- set itemsLoaded(promise) {
1404
- this._itemsLoaded = promise;
1405
- }
1406
1390
  validateValueAvailability(setting, value) {
1407
1391
  if (!boolValue(setting) || !value) {
1408
1392
  return true;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@formio/js",
3
- "version": "5.0.0-dev.5822.ae2ec5b",
3
+ "version": "5.0.0-dev.5826.02fa4d9",
4
4
  "description": "JavaScript powered Forms with JSON Form Builder",
5
5
  "main": "lib/cjs/index.js",
6
6
  "exports": {