@formio/js 5.0.0-dev.5933.606556f → 5.0.0-dev.5936.905c79f

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.
@@ -1085,6 +1085,12 @@ class WebformBuilder extends Component_1.default {
1085
1085
  parentComponent.tabs[tabIndex].splice(index, 1, newComp);
1086
1086
  newComp.checkValidity = () => true;
1087
1087
  newComp.build(defaultValueComponent.element);
1088
+ if (this.preview && !this.preview.defaultChanged) {
1089
+ const defaultValue = lodash_1.default.get(this.preview._data, this.editForm._data.key);
1090
+ if (lodash_1.default.isObject(defaultValue) && !lodash_1.default.isArray(defaultValue)) {
1091
+ this.editForm._data.defaultValue = defaultValue;
1092
+ }
1093
+ }
1088
1094
  }
1089
1095
  }
1090
1096
  else {
@@ -1095,6 +1101,7 @@ class WebformBuilder extends Component_1.default {
1095
1101
  path.unshift(component.key);
1096
1102
  dataPath = (0, utils_1.getStringFromComponentPath)(path);
1097
1103
  }
1104
+ this.preview.defaultChanged = true;
1098
1105
  lodash_1.default.set(this.preview._data, dataPath, changed.value);
1099
1106
  lodash_1.default.set(this.webform._data, dataPath, changed.value);
1100
1107
  }
package/lib/cjs/Wizard.js CHANGED
@@ -602,7 +602,10 @@ class Wizard extends Webform_1.default {
602
602
  }
603
603
  this.redraw().then(() => {
604
604
  this.checkData(this.submission.data);
605
- this.validateCurrentPage();
605
+ const errors = this.submitted ? this.validate(this.localData, { dirty: true }) : this.validateCurrentPage();
606
+ if (this.alert) {
607
+ this.showErrors(errors, true, true);
608
+ }
606
609
  });
607
610
  return Promise.resolve();
608
611
  }
@@ -699,9 +702,11 @@ class Wizard extends Webform_1.default {
699
702
  });
700
703
  });
701
704
  }
702
- // Validate the form, before go to the next page
703
- const errors = this.validateCurrentPage({ dirty: true });
704
- if (errors.length === 0) {
705
+ // Validate the form before going to the next page
706
+ const currentPageErrors = this.validateCurrentPage({ dirty: true });
707
+ const errors = this.submitted ? this.validate(this.localData, { dirty: true }) : currentPageErrors;
708
+ // allow going to the next page if the current page is valid, even if there are form level errors
709
+ if (currentPageErrors.length === 0) {
705
710
  this.checkData(this.submission.data);
706
711
  return this.beforePage(true).then(() => {
707
712
  return this.setPage(this.getNextPage()).then(() => {
@@ -716,7 +721,7 @@ class Wizard extends Webform_1.default {
716
721
  else {
717
722
  this.currentPage.components.forEach((comp) => comp.setPristine(false));
718
723
  this.scrollIntoView(this.element, true);
719
- return Promise.reject(super.showErrors(errors, true));
724
+ return Promise.reject(this.showErrors(errors, true));
720
725
  }
721
726
  }
722
727
  validateCurrentPage(flags = {}) {
@@ -921,10 +926,7 @@ class Wizard extends Webform_1.default {
921
926
  return components.reduce((check, comp) => comp.checkValidity(data, dirty, row, currentPageOnly, childErrors) && check, true);
922
927
  }
923
928
  get errors() {
924
- if (!this.isLastPage()) {
925
- return this.currentPage.errors;
926
- }
927
- return super.errors;
929
+ return !this.isLastPage() && !this.submitted ? this.currentPage.errors : super.errors;
928
930
  }
929
931
  focusOnComponent(key) {
930
932
  const component = this.getComponent(key);
@@ -413,7 +413,6 @@ class DataGridComponent extends NestedArrayComponent_1.default {
413
413
  });
414
414
  this.checkConditions();
415
415
  this.triggerChange();
416
- this.triggerChange({ modified: true });
417
416
  this.redraw().then(() => {
418
417
  this.focusOnNewRowElement(this.rows[index]);
419
418
  });
@@ -493,9 +492,6 @@ class DataGridComponent extends NestedArrayComponent_1.default {
493
492
  const options = lodash_1.default.clone(this.options);
494
493
  options.name += `[${rowIndex}]`;
495
494
  options.row = `${rowIndex}-${colIndex}`;
496
- options.onChange = (flags, changed, modified) => {
497
- this.triggerChange({ modified });
498
- };
499
495
  let columnComponent;
500
496
  if (this.builderMode) {
501
497
  col.id = col.id + rowIndex;
@@ -27,6 +27,7 @@ export default class RadioComponent extends ListComponent {
27
27
  itemsLoadedResolve: ((value: any) => void) | undefined;
28
28
  optionsLoaded: boolean | undefined;
29
29
  loadedOptions: any[] | undefined;
30
+ valuesMap: Map<any, any> | undefined;
30
31
  beforeSubmit(): Promise<any>;
31
32
  render(): import("../_classes/field/Field").default;
32
33
  attach(element: any): Promise<void>;
@@ -35,10 +36,13 @@ export default class RadioComponent extends ListComponent {
35
36
  validateValueAvailability(setting: any, value: any): boolean;
36
37
  getValueAsString(value: any, options?: {}): any;
37
38
  setValueAt(index: any, value: any): void;
39
+ prepareValue(item: any, options?: {}): any;
40
+ getValueByInput(input: any): any;
38
41
  loadItems(url: any, search: any, headers: any, options: any, method: any, body: any): void;
39
42
  loadItemsFromMetadata(): void;
40
43
  setItems(items: any): void;
41
44
  setSelectedClasses(): void;
45
+ setMetadata(value: any): void;
42
46
  updateValue(value: any, flags: any): boolean;
43
47
  currentValue: any;
44
48
  }
@@ -7,6 +7,7 @@ const lodash_1 = __importDefault(require("lodash"));
7
7
  const ListComponent_1 = __importDefault(require("../_classes/list/ListComponent"));
8
8
  const Formio_1 = require("../../Formio");
9
9
  const utils_1 = require("../../utils/utils");
10
+ const uuid_1 = require("uuid");
10
11
  class RadioComponent extends ListComponent_1.default {
11
12
  static schema(...extend) {
12
13
  return ListComponent_1.default.schema({
@@ -142,6 +143,7 @@ class RadioComponent extends ListComponent_1.default {
142
143
  });
143
144
  this.optionsLoaded = !this.component.dataSrc || this.component.dataSrc === 'values';
144
145
  this.loadedOptions = [];
146
+ this.valuesMap = new Map();
145
147
  if (!this.visible) {
146
148
  this.itemsLoadedResolve();
147
149
  }
@@ -181,9 +183,12 @@ class RadioComponent extends ListComponent_1.default {
181
183
  if (!lodash_1.default.isString(this.dataValue)) {
182
184
  dataValue = lodash_1.default.toString(this.dataValue);
183
185
  }
184
- if (this.isSelectURL && lodash_1.default.isObject(this.loadedOptions[index].value)) {
185
- const optionValue = this.component.dataType === 'string' ? JSON.stringify(this.loadedOptions[index].value) : this.loadedOptions[index].value;
186
- input.checked = lodash_1.default.isEqual(optionValue, this.dataValue);
186
+ if (this.isSelectURL) {
187
+ const valueKey = this.loadedOptions[index].value;
188
+ const optionValue = this.valuesMap.has(valueKey)
189
+ ? this.valuesMap.get(valueKey)
190
+ : valueKey;
191
+ input.checked = lodash_1.default.isEqual(this.normalizeValue(optionValue), this.dataValue);
187
192
  }
188
193
  else {
189
194
  input.checked = (dataValue === input.value && (input.value || this.component.dataSrc !== 'url'));
@@ -220,9 +225,14 @@ class RadioComponent extends ListComponent_1.default {
220
225
  let value = this.component.inputType === 'checkbox' ? '' : this.dataValue;
221
226
  this.refs.input.forEach((input, index) => {
222
227
  if (input.checked) {
223
- value = (this.isSelectURL && lodash_1.default.isObject(this.loadedOptions[index].value)) ?
224
- this.loadedOptions[index].value :
225
- input.value;
228
+ if (!this.isSelectURL) {
229
+ value = input.value;
230
+ return;
231
+ }
232
+ const optionValue = this.loadedOptions[index].value;
233
+ value = this.valuesMap.has(optionValue)
234
+ ? this.valuesMap.get(optionValue)
235
+ : optionValue;
226
236
  }
227
237
  });
228
238
  return value;
@@ -266,8 +276,8 @@ class RadioComponent extends ListComponent_1.default {
266
276
  }
267
277
  setValueAt(index, value) {
268
278
  if (this.refs.input && this.refs.input[index] && value !== null && value !== undefined) {
269
- const inputValue = this.refs.input[index].value;
270
- this.refs.input[index].checked = (inputValue === value.toString());
279
+ const inputValue = this.getValueByInput(this.refs.input[index]);
280
+ this.refs.input[index].checked = lodash_1.default.isEqual(inputValue, value);
271
281
  }
272
282
  }
273
283
  get shouldLoad() {
@@ -277,6 +287,23 @@ class RadioComponent extends ListComponent_1.default {
277
287
  }
278
288
  return super.shouldLoad;
279
289
  }
290
+ prepareValue(item, options = {}) {
291
+ const value = this.component.valueProperty && !options.skipValueProperty
292
+ ? lodash_1.default.get(item, this.component.valueProperty)
293
+ : item;
294
+ if (this.component.type === 'radio' && typeof value !== 'string') {
295
+ const uuid = (0, uuid_1.v4)();
296
+ this.valuesMap.set(uuid, value);
297
+ return uuid;
298
+ }
299
+ return value;
300
+ }
301
+ getValueByInput(input) {
302
+ const inputValue = input.value;
303
+ return this.valuesMap.has(inputValue)
304
+ ? this.valuesMap.get(inputValue)
305
+ : inputValue;
306
+ }
280
307
  loadItems(url, search, headers, options, method, body) {
281
308
  if (this.optionsLoaded) {
282
309
  this.itemsLoadedResolve();
@@ -327,7 +354,7 @@ class RadioComponent extends ListComponent_1.default {
327
354
  label: this.itemTemplate(item)
328
355
  };
329
356
  if (lodash_1.default.isEqual(item, this.selectData || lodash_1.default.pick(this.dataValue, lodash_1.default.keys(item)))) {
330
- this.loadedOptions[i].value = this.dataValue;
357
+ this.loadedOptions[i].value = this.prepareValue(this.dataValue, { skipValueProperty: true });
331
358
  }
332
359
  });
333
360
  this.optionsLoaded = true;
@@ -337,12 +364,15 @@ class RadioComponent extends ListComponent_1.default {
337
364
  const listData = [];
338
365
  items === null || items === void 0 ? void 0 : items.forEach((item, i) => {
339
366
  const valueAtProperty = lodash_1.default.get(item, this.component.valueProperty);
340
- this.loadedOptions[i] = {
341
- value: this.component.valueProperty ? valueAtProperty : item,
342
- label: this.component.valueProperty ? this.itemTemplate(item, valueAtProperty) : this.itemTemplate(item, item, i)
343
- };
344
- listData.push(this.templateData[this.component.valueProperty ? valueAtProperty : i]);
345
- const value = this.loadedOptions[i].value;
367
+ const value = this.prepareValue(item);
368
+ const label = this.component.valueProperty
369
+ ? this.itemTemplate(item, valueAtProperty, i)
370
+ : this.itemTemplate(item, item, i);
371
+ this.loadedOptions[i] = { label, value };
372
+ listData.push(this.templateData[i]);
373
+ if (this.valuesMap.has(value)) {
374
+ this.templateData[value] = this.templateData[i];
375
+ }
346
376
  if (!this.isRadio && (lodash_1.default.isObject(value) || lodash_1.default.isBoolean(value) || lodash_1.default.isUndefined(value))) {
347
377
  this.loadedOptions[i].invalid = true;
348
378
  }
@@ -365,7 +395,9 @@ class RadioComponent extends ListComponent_1.default {
365
395
  const value = this.dataValue;
366
396
  this.refs.wrapper.forEach((wrapper, index) => {
367
397
  const input = this.refs.input[index];
368
- const checked = (input.type === 'checkbox') ? value[input.value] || input.checked : (input.value.toString() === value.toString());
398
+ const checked = (input.type === 'checkbox')
399
+ ? value[input.value] || input.checked
400
+ : lodash_1.default.isEqual(this.normalizeValue(this.getValueByInput(input)), value);
369
401
  if (checked) {
370
402
  //add class to container when selected
371
403
  this.addClass(wrapper, this.optionSelectedClass);
@@ -379,10 +411,25 @@ class RadioComponent extends ListComponent_1.default {
379
411
  });
380
412
  }
381
413
  }
414
+ setMetadata(value) {
415
+ let key = value;
416
+ if (typeof value !== 'string') {
417
+ const checkedInput = Array.prototype.find.call(this.refs.input, (input => input.type === 'radio' && input.getAttribute('checked')));
418
+ key = (checkedInput === null || checkedInput === void 0 ? void 0 : checkedInput.value) || key;
419
+ }
420
+ if (this.isSelectURL && this.templateData && this.templateData[key]) {
421
+ const submission = this.root.submission;
422
+ if (!submission.metadata.selectData) {
423
+ submission.metadata.selectData = {};
424
+ }
425
+ lodash_1.default.set(submission.metadata.selectData, this.path, this.templateData[key]);
426
+ }
427
+ }
382
428
  updateValue(value, flags) {
383
429
  const changed = super.updateValue(value, flags);
384
430
  if (changed) {
385
431
  this.setSelectedClasses();
432
+ this.setMetadata(this.dataValue);
386
433
  }
387
434
  if (!flags || !flags.modified || !this.isRadio) {
388
435
  if (changed) {
@@ -438,14 +485,10 @@ class RadioComponent extends ListComponent_1.default {
438
485
  value = !(!value || value.toString() === 'false');
439
486
  break;
440
487
  }
441
- if (this.isSelectURL && this.templateData && this.templateData[value]) {
442
- const submission = this.root.submission;
443
- if (!submission.metadata.selectData) {
444
- submission.metadata.selectData = {};
445
- }
446
- lodash_1.default.set(submission.metadata.selectData, this.path, this.templateData[value]);
447
- }
448
488
  return super.normalizeValue(value);
449
489
  }
490
+ isSingleInputValue() {
491
+ return true;
492
+ }
450
493
  }
451
494
  exports.default = RadioComponent;
@@ -139,6 +139,14 @@ class SelectBoxesComponent extends Radio_1.default {
139
139
  checkedValues.forEach((value) => selectData.push(this.templateData[value]));
140
140
  lodash_1.default.set(submission.metadata.selectData, this.path, selectData);
141
141
  }
142
+ // Ensure that for dataSrc == 'values' that there are not any other superfluous values.
143
+ if (this.component.dataSrc === 'values') {
144
+ for (const key in value) {
145
+ if (!this.component.values.find((val) => val.value === key)) {
146
+ delete value[key];
147
+ }
148
+ }
149
+ }
142
150
  return value;
143
151
  }
144
152
  /**
@@ -1069,6 +1069,12 @@ export default class WebformBuilder extends Component {
1069
1069
  parentComponent.tabs[tabIndex].splice(index, 1, newComp);
1070
1070
  newComp.checkValidity = () => true;
1071
1071
  newComp.build(defaultValueComponent.element);
1072
+ if (this.preview && !this.preview.defaultChanged) {
1073
+ const defaultValue = _.get(this.preview._data, this.editForm._data.key);
1074
+ if (_.isObject(defaultValue) && !_.isArray(defaultValue)) {
1075
+ this.editForm._data.defaultValue = defaultValue;
1076
+ }
1077
+ }
1072
1078
  }
1073
1079
  }
1074
1080
  else {
@@ -1079,6 +1085,7 @@ export default class WebformBuilder extends Component {
1079
1085
  path.unshift(component.key);
1080
1086
  dataPath = getStringFromComponentPath(path);
1081
1087
  }
1088
+ this.preview.defaultChanged = true;
1082
1089
  _.set(this.preview._data, dataPath, changed.value);
1083
1090
  _.set(this.webform._data, dataPath, changed.value);
1084
1091
  }
package/lib/mjs/Wizard.js CHANGED
@@ -594,7 +594,10 @@ export default class Wizard extends Webform {
594
594
  }
595
595
  this.redraw().then(() => {
596
596
  this.checkData(this.submission.data);
597
- this.validateCurrentPage();
597
+ const errors = this.submitted ? this.validate(this.localData, { dirty: true }) : this.validateCurrentPage();
598
+ if (this.alert) {
599
+ this.showErrors(errors, true, true);
600
+ }
598
601
  });
599
602
  return Promise.resolve();
600
603
  }
@@ -689,9 +692,11 @@ export default class Wizard extends Webform {
689
692
  });
690
693
  });
691
694
  }
692
- // Validate the form, before go to the next page
693
- const errors = this.validateCurrentPage({ dirty: true });
694
- if (errors.length === 0) {
695
+ // Validate the form before going to the next page
696
+ const currentPageErrors = this.validateCurrentPage({ dirty: true });
697
+ const errors = this.submitted ? this.validate(this.localData, { dirty: true }) : currentPageErrors;
698
+ // allow going to the next page if the current page is valid, even if there are form level errors
699
+ if (currentPageErrors.length === 0) {
695
700
  this.checkData(this.submission.data);
696
701
  return this.beforePage(true).then(() => {
697
702
  return this.setPage(this.getNextPage()).then(() => {
@@ -706,7 +711,7 @@ export default class Wizard extends Webform {
706
711
  else {
707
712
  this.currentPage.components.forEach((comp) => comp.setPristine(false));
708
713
  this.scrollIntoView(this.element, true);
709
- return Promise.reject(super.showErrors(errors, true));
714
+ return Promise.reject(this.showErrors(errors, true));
710
715
  }
711
716
  }
712
717
  validateCurrentPage(flags = {}) {
@@ -908,10 +913,7 @@ export default class Wizard extends Webform {
908
913
  return components.reduce((check, comp) => comp.checkValidity(data, dirty, row, currentPageOnly, childErrors) && check, true);
909
914
  }
910
915
  get errors() {
911
- if (!this.isLastPage()) {
912
- return this.currentPage.errors;
913
- }
914
- return super.errors;
916
+ return !this.isLastPage() && !this.submitted ? this.currentPage.errors : super.errors;
915
917
  }
916
918
  focusOnComponent(key) {
917
919
  const component = this.getComponent(key);
@@ -410,7 +410,6 @@ export default class DataGridComponent extends NestedArrayComponent {
410
410
  });
411
411
  this.checkConditions();
412
412
  this.triggerChange();
413
- this.triggerChange({ modified: true });
414
413
  this.redraw().then(() => {
415
414
  this.focusOnNewRowElement(this.rows[index]);
416
415
  });
@@ -489,9 +488,6 @@ export default class DataGridComponent extends NestedArrayComponent {
489
488
  const options = _.clone(this.options);
490
489
  options.name += `[${rowIndex}]`;
491
490
  options.row = `${rowIndex}-${colIndex}`;
492
- options.onChange = (flags, changed, modified) => {
493
- this.triggerChange({ modified });
494
- };
495
491
  let columnComponent;
496
492
  if (this.builderMode) {
497
493
  col.id = col.id + rowIndex;
@@ -27,6 +27,7 @@ export default class RadioComponent extends ListComponent {
27
27
  itemsLoadedResolve: ((value: any) => void) | undefined;
28
28
  optionsLoaded: boolean | undefined;
29
29
  loadedOptions: any[] | undefined;
30
+ valuesMap: Map<any, any> | undefined;
30
31
  beforeSubmit(): Promise<any>;
31
32
  render(): import("../_classes/field/Field").default;
32
33
  attach(element: any): Promise<void>;
@@ -35,10 +36,13 @@ export default class RadioComponent extends ListComponent {
35
36
  validateValueAvailability(setting: any, value: any): boolean;
36
37
  getValueAsString(value: any, options?: {}): any;
37
38
  setValueAt(index: any, value: any): void;
39
+ prepareValue(item: any, options?: {}): any;
40
+ getValueByInput(input: any): any;
38
41
  loadItems(url: any, search: any, headers: any, options: any, method: any, body: any): void;
39
42
  loadItemsFromMetadata(): void;
40
43
  setItems(items: any): void;
41
44
  setSelectedClasses(): void;
45
+ setMetadata(value: any): void;
42
46
  updateValue(value: any, flags: any): boolean;
43
47
  currentValue: any;
44
48
  }
@@ -2,6 +2,7 @@ import _ from 'lodash';
2
2
  import ListComponent from '../_classes/list/ListComponent';
3
3
  import { Formio } from '../../Formio';
4
4
  import { boolValue, componentValueTypes, getComponentSavedTypes } from '../../utils/utils';
5
+ import { v4 as uuidv4 } from 'uuid';
5
6
  export default class RadioComponent extends ListComponent {
6
7
  static schema(...extend) {
7
8
  return ListComponent.schema({
@@ -142,6 +143,7 @@ export default class RadioComponent extends ListComponent {
142
143
  });
143
144
  this.optionsLoaded = !this.component.dataSrc || this.component.dataSrc === 'values';
144
145
  this.loadedOptions = [];
146
+ this.valuesMap = new Map();
145
147
  if (!this.visible) {
146
148
  this.itemsLoadedResolve();
147
149
  }
@@ -181,9 +183,12 @@ export default class RadioComponent extends ListComponent {
181
183
  if (!_.isString(this.dataValue)) {
182
184
  dataValue = _.toString(this.dataValue);
183
185
  }
184
- if (this.isSelectURL && _.isObject(this.loadedOptions[index].value)) {
185
- const optionValue = this.component.dataType === 'string' ? JSON.stringify(this.loadedOptions[index].value) : this.loadedOptions[index].value;
186
- input.checked = _.isEqual(optionValue, this.dataValue);
186
+ if (this.isSelectURL) {
187
+ const valueKey = this.loadedOptions[index].value;
188
+ const optionValue = this.valuesMap.has(valueKey)
189
+ ? this.valuesMap.get(valueKey)
190
+ : valueKey;
191
+ input.checked = _.isEqual(this.normalizeValue(optionValue), this.dataValue);
187
192
  }
188
193
  else {
189
194
  input.checked = (dataValue === input.value && (input.value || this.component.dataSrc !== 'url'));
@@ -220,9 +225,14 @@ export default class RadioComponent extends ListComponent {
220
225
  let value = this.component.inputType === 'checkbox' ? '' : this.dataValue;
221
226
  this.refs.input.forEach((input, index) => {
222
227
  if (input.checked) {
223
- value = (this.isSelectURL && _.isObject(this.loadedOptions[index].value)) ?
224
- this.loadedOptions[index].value :
225
- input.value;
228
+ if (!this.isSelectURL) {
229
+ value = input.value;
230
+ return;
231
+ }
232
+ const optionValue = this.loadedOptions[index].value;
233
+ value = this.valuesMap.has(optionValue)
234
+ ? this.valuesMap.get(optionValue)
235
+ : optionValue;
226
236
  }
227
237
  });
228
238
  return value;
@@ -266,8 +276,8 @@ export default class RadioComponent extends ListComponent {
266
276
  }
267
277
  setValueAt(index, value) {
268
278
  if (this.refs.input && this.refs.input[index] && value !== null && value !== undefined) {
269
- const inputValue = this.refs.input[index].value;
270
- this.refs.input[index].checked = (inputValue === value.toString());
279
+ const inputValue = this.getValueByInput(this.refs.input[index]);
280
+ this.refs.input[index].checked = _.isEqual(inputValue, value);
271
281
  }
272
282
  }
273
283
  get shouldLoad() {
@@ -277,6 +287,23 @@ export default class RadioComponent extends ListComponent {
277
287
  }
278
288
  return super.shouldLoad;
279
289
  }
290
+ prepareValue(item, options = {}) {
291
+ const value = this.component.valueProperty && !options.skipValueProperty
292
+ ? _.get(item, this.component.valueProperty)
293
+ : item;
294
+ if (this.component.type === 'radio' && typeof value !== 'string') {
295
+ const uuid = uuidv4();
296
+ this.valuesMap.set(uuid, value);
297
+ return uuid;
298
+ }
299
+ return value;
300
+ }
301
+ getValueByInput(input) {
302
+ const inputValue = input.value;
303
+ return this.valuesMap.has(inputValue)
304
+ ? this.valuesMap.get(inputValue)
305
+ : inputValue;
306
+ }
280
307
  loadItems(url, search, headers, options, method, body) {
281
308
  if (this.optionsLoaded) {
282
309
  this.itemsLoadedResolve();
@@ -327,7 +354,7 @@ export default class RadioComponent extends ListComponent {
327
354
  label: this.itemTemplate(item)
328
355
  };
329
356
  if (_.isEqual(item, this.selectData || _.pick(this.dataValue, _.keys(item)))) {
330
- this.loadedOptions[i].value = this.dataValue;
357
+ this.loadedOptions[i].value = this.prepareValue(this.dataValue, { skipValueProperty: true });
331
358
  }
332
359
  });
333
360
  this.optionsLoaded = true;
@@ -337,12 +364,15 @@ export default class RadioComponent extends ListComponent {
337
364
  const listData = [];
338
365
  items?.forEach((item, i) => {
339
366
  const valueAtProperty = _.get(item, this.component.valueProperty);
340
- this.loadedOptions[i] = {
341
- value: this.component.valueProperty ? valueAtProperty : item,
342
- label: this.component.valueProperty ? this.itemTemplate(item, valueAtProperty) : this.itemTemplate(item, item, i)
343
- };
344
- listData.push(this.templateData[this.component.valueProperty ? valueAtProperty : i]);
345
- const value = this.loadedOptions[i].value;
367
+ const value = this.prepareValue(item);
368
+ const label = this.component.valueProperty
369
+ ? this.itemTemplate(item, valueAtProperty, i)
370
+ : this.itemTemplate(item, item, i);
371
+ this.loadedOptions[i] = { label, value };
372
+ listData.push(this.templateData[i]);
373
+ if (this.valuesMap.has(value)) {
374
+ this.templateData[value] = this.templateData[i];
375
+ }
346
376
  if (!this.isRadio && (_.isObject(value) || _.isBoolean(value) || _.isUndefined(value))) {
347
377
  this.loadedOptions[i].invalid = true;
348
378
  }
@@ -365,7 +395,9 @@ export default class RadioComponent extends ListComponent {
365
395
  const value = this.dataValue;
366
396
  this.refs.wrapper.forEach((wrapper, index) => {
367
397
  const input = this.refs.input[index];
368
- const checked = (input.type === 'checkbox') ? value[input.value] || input.checked : (input.value.toString() === value.toString());
398
+ const checked = (input.type === 'checkbox')
399
+ ? value[input.value] || input.checked
400
+ : _.isEqual(this.normalizeValue(this.getValueByInput(input)), value);
369
401
  if (checked) {
370
402
  //add class to container when selected
371
403
  this.addClass(wrapper, this.optionSelectedClass);
@@ -379,10 +411,25 @@ export default class RadioComponent extends ListComponent {
379
411
  });
380
412
  }
381
413
  }
414
+ setMetadata(value) {
415
+ let key = value;
416
+ if (typeof value !== 'string') {
417
+ const checkedInput = Array.prototype.find.call(this.refs.input, (input => input.type === 'radio' && input.getAttribute('checked')));
418
+ key = checkedInput?.value || key;
419
+ }
420
+ if (this.isSelectURL && this.templateData && this.templateData[key]) {
421
+ const submission = this.root.submission;
422
+ if (!submission.metadata.selectData) {
423
+ submission.metadata.selectData = {};
424
+ }
425
+ _.set(submission.metadata.selectData, this.path, this.templateData[key]);
426
+ }
427
+ }
382
428
  updateValue(value, flags) {
383
429
  const changed = super.updateValue(value, flags);
384
430
  if (changed) {
385
431
  this.setSelectedClasses();
432
+ this.setMetadata(this.dataValue);
386
433
  }
387
434
  if (!flags || !flags.modified || !this.isRadio) {
388
435
  if (changed) {
@@ -438,13 +485,9 @@ export default class RadioComponent extends ListComponent {
438
485
  value = !(!value || value.toString() === 'false');
439
486
  break;
440
487
  }
441
- if (this.isSelectURL && this.templateData && this.templateData[value]) {
442
- const submission = this.root.submission;
443
- if (!submission.metadata.selectData) {
444
- submission.metadata.selectData = {};
445
- }
446
- _.set(submission.metadata.selectData, this.path, this.templateData[value]);
447
- }
448
488
  return super.normalizeValue(value);
449
489
  }
490
+ isSingleInputValue() {
491
+ return true;
492
+ }
450
493
  }
@@ -141,6 +141,14 @@ export default class SelectBoxesComponent extends RadioComponent {
141
141
  checkedValues.forEach((value) => selectData.push(this.templateData[value]));
142
142
  _.set(submission.metadata.selectData, this.path, selectData);
143
143
  }
144
+ // Ensure that for dataSrc == 'values' that there are not any other superfluous values.
145
+ if (this.component.dataSrc === 'values') {
146
+ for (const key in value) {
147
+ if (!this.component.values.find((val) => val.value === key)) {
148
+ delete value[key];
149
+ }
150
+ }
151
+ }
144
152
  return value;
145
153
  }
146
154
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@formio/js",
3
- "version": "5.0.0-dev.5933.606556f",
3
+ "version": "5.0.0-dev.5936.905c79f",
4
4
  "description": "JavaScript powered Forms with JSON Form Builder",
5
5
  "main": "lib/cjs/index.js",
6
6
  "exports": {