@formio/js 5.0.0-dev.5834.98680ce → 5.0.0-dev.5834.b72f609

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.
@@ -1237,9 +1237,15 @@ class Webform extends NestedDataComponent_1.default {
1237
1237
  * @param {any} changes - The changes that have occured in the form.
1238
1238
  */
1239
1239
  onChange(flags, changed, modified, changes) {
1240
+ var _a;
1240
1241
  flags = flags || {};
1241
1242
  let isChangeEventEmitted = false;
1242
- super.onChange(flags, true);
1243
+ if (((_a = this.parent) === null || _a === void 0 ? void 0 : _a.subForm) === this) {
1244
+ super.onChange(Object.assign(Object.assign({}, flags), { modified }), false);
1245
+ }
1246
+ else {
1247
+ super.onChange(flags, true);
1248
+ }
1243
1249
  const value = lodash_1.default.clone(this.submission);
1244
1250
  flags.changed = value.changed = changed;
1245
1251
  flags.changes = changes;
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const Component_1 = __importDefault(require("./_classes/component/Component"));
7
7
  const utils_1 = __importDefault(require("./_classes/component/editForm/utils"));
8
8
  const Component_form_1 = __importDefault(require("./_classes/component/Component.form"));
9
+ const utils_2 = require("../utils/utils");
9
10
  const lodash_1 = __importDefault(require("lodash"));
10
11
  class Components {
11
12
  static set EditFormUtils(value) {
@@ -56,7 +57,8 @@ class Components {
56
57
  static getComponentPath(component) {
57
58
  var _a;
58
59
  let path = '';
59
- if (component.component.key) {
60
+ const componentKey = (0, utils_2.getComponentKey)(component.component);
61
+ if (componentKey) {
60
62
  let thisPath = ((_a = component.options) === null || _a === void 0 ? void 0 : _a.parent) || component;
61
63
  while (thisPath && !thisPath.allowData && thisPath.parent) {
62
64
  thisPath = thisPath.parent;
@@ -68,7 +70,10 @@ class Components {
68
70
  const rowIndex = component.row;
69
71
  const rowIndexPath = rowIndex && !['container'].includes(thisPath.component.type) ? `[${Number.parseInt(rowIndex)}]` : '';
70
72
  path = `${thisPath.path}${rowIndexPath}.`;
71
- path += component.component.key;
73
+ if (rowIndexPath && (0, utils_2.getModelType)(thisPath) === 'nestedDataArray') {
74
+ path = `${path}data.`;
75
+ }
76
+ path += componentKey;
72
77
  return lodash_1.default.trim(path, '.');
73
78
  }
74
79
  return path;
@@ -1757,12 +1757,12 @@ class Component extends Element_1.default {
1757
1757
  var _a, _b, _c;
1758
1758
  if ((_a = this.root) === null || _a === void 0 ? void 0 : _a.currentSelection) {
1759
1759
  if ((_b = this.refs.input) === null || _b === void 0 ? void 0 : _b.length) {
1760
- const { selection, index } = this.root.currentSelection;
1760
+ const { index } = this.root.currentSelection;
1761
1761
  let input = this.refs.input[index];
1762
1762
  const isInputRangeSelectable = (i) => /text|search|password|tel|url/i.test((i === null || i === void 0 ? void 0 : i.type) || '');
1763
1763
  if (input) {
1764
1764
  if (isInputRangeSelectable(input)) {
1765
- input.setSelectionRange(...selection);
1765
+ input.setSelectionRange(input.value.length, input.value.length);
1766
1766
  }
1767
1767
  }
1768
1768
  else {
@@ -2966,7 +2966,7 @@ class Component extends Element_1.default {
2966
2966
  flags.dirty = true;
2967
2967
  }
2968
2968
  if (flags.fromSubmission && this.hasValue(data)) {
2969
- flags.dirty = true;
2969
+ flags.dirty = this.pristine && this.component.protected ? false : true;
2970
2970
  }
2971
2971
  this.setDirty(flags.dirty);
2972
2972
  return this.setComponentValidity(errors, flags.dirty, flags.silentCheck, flags.fromSubmission);
@@ -2992,6 +2992,7 @@ class Component extends Element_1.default {
2992
2992
  value: this.validationValue,
2993
2993
  path: this.path || this.component.key,
2994
2994
  instance: this,
2995
+ form: this.root ? this.root._form : {},
2995
2996
  scope: { errors: [] },
2996
2997
  processors: [
2997
2998
  process_1.validateProcessInfo
@@ -3468,14 +3469,16 @@ class Component extends Element_1.default {
3468
3469
  window.scrollTo(verticalOnly ? window.scrollX : left + window.scrollX, top + window.scrollY);
3469
3470
  }
3470
3471
  focus(index) {
3471
- var _a, _b, _c;
3472
+ var _a, _b, _c, _d;
3472
3473
  if ('beforeFocus' in this.parent) {
3473
3474
  this.parent.beforeFocus(this);
3474
3475
  }
3475
- index = index || ((_a = this.refs.input) === null || _a === void 0 ? void 0 : _a.length) - 1;
3476
- if ((_b = this.refs.input) === null || _b === void 0 ? void 0 : _b.length) {
3476
+ if (!index && !lodash_1.default.isNumber(index) && ((_b = (_a = this.refs) === null || _a === void 0 ? void 0 : _a.input) === null || _b === void 0 ? void 0 : _b.length)) {
3477
+ index = this.refs.input.length - 1;
3478
+ }
3479
+ if ((_c = this.refs.input) === null || _c === void 0 ? void 0 : _c.length) {
3477
3480
  const focusingInput = this.refs.input[index];
3478
- if (((_c = this.component.widget) === null || _c === void 0 ? void 0 : _c.type) === 'calendar') {
3481
+ if (((_d = this.component.widget) === null || _d === void 0 ? void 0 : _d.type) === 'calendar') {
3479
3482
  const sibling = focusingInput.nextSibling;
3480
3483
  if (sibling) {
3481
3484
  sibling.focus();
@@ -190,6 +190,7 @@ class ListComponent extends Field_1.default {
190
190
  return;
191
191
  }
192
192
  let { url } = this.component.data;
193
+ url = lodash_1.default.trim(url);
193
194
  let method;
194
195
  let body;
195
196
  if (url.startsWith('/')) {
@@ -214,6 +214,16 @@ class AddressComponent extends Container_1.default {
214
214
  isValueInLegacyFormat(value) {
215
215
  return value && !value.mode;
216
216
  }
217
+ set dataValue(value) {
218
+ super.dataValue = value;
219
+ }
220
+ get dataValue() {
221
+ const resultValue = lodash_1.default.get(this._data, this.component.path);
222
+ if (!lodash_1.default.isArray(resultValue) && this.component.multiple) {
223
+ return [resultValue];
224
+ }
225
+ return super.dataValue;
226
+ }
217
227
  normalizeValue(value) {
218
228
  return (this.manualModeEnabled && this.isValueInLegacyFormat(value))
219
229
  ? {
@@ -286,7 +286,7 @@ class DayComponent extends Field_1.default {
286
286
  if (!this.component.fields.day.hide && maxDay) {
287
287
  this.refs.day.max = maxDay;
288
288
  }
289
- if (maxDay && day > maxDay) {
289
+ if (maxDay && day > maxDay && this.refs.day) {
290
290
  this.refs.day.value = this.refs.day.max;
291
291
  }
292
292
  updateValueAndSaveFocus(this.refs.month, 'month')();
@@ -496,27 +496,40 @@ class DayComponent extends Field_1.default {
496
496
  if (defaultValue) {
497
497
  defaults = defaultValue.split('/').map(x => parseInt(x, 10));
498
498
  }
499
+ const isModalEditClosed = this.component.modalEdit && !this.componentModal.isOpened;
499
500
  if (this.showDay && this.refs.day) {
500
- day = parseInt(this.refs.day.value, 10);
501
+ day = (this.refs.day.value === '' && !isModalEditClosed) ? '' : parseInt(this.refs.day.value, 10);
501
502
  }
502
- if (day === undefined || lodash_1.default.isNaN(day)) {
503
- day = defaults[DAY] && !lodash_1.default.isNaN(defaults[DAY]) ? defaults[DAY] : 0;
503
+ if (day === undefined || lodash_1.default.isNaN(day) || value) {
504
+ day = (defaults.length !== 3)
505
+ ? this.getDayWithHiddenFields(defaults).day
506
+ : (defaults[DAY] && !lodash_1.default.isNaN(defaults[DAY]) ? defaults[DAY] : 0);
504
507
  }
505
508
  if (this.showMonth && this.refs.month) {
506
509
  // Months are 0 indexed.
507
- month = parseInt(this.refs.month.value, 10);
510
+ month = (this.refs.month.value === '' && !isModalEditClosed) ? '' : parseInt(this.refs.month.value, 10);
508
511
  }
509
- if (month === undefined || lodash_1.default.isNaN(month)) {
510
- month = defaults[MONTH] && !lodash_1.default.isNaN(defaults[MONTH]) ? defaults[MONTH] : 0;
512
+ if (month === undefined || lodash_1.default.isNaN(month) || value) {
513
+ month = (defaults.length !== 3)
514
+ ? this.getDayWithHiddenFields(defaults).month
515
+ : (defaults[MONTH] && !lodash_1.default.isNaN(defaults[MONTH]) ? defaults[MONTH] : 0);
511
516
  }
512
517
  if (this.showYear && this.refs.year) {
513
- year = parseInt(this.refs.year.value);
518
+ year = (this.refs.year.value === '' && !isModalEditClosed) ? '' : parseInt(this.refs.year.value);
514
519
  }
515
- if (year === undefined || lodash_1.default.isNaN(year)) {
516
- year = defaults[YEAR] && !lodash_1.default.isNaN(defaults[YEAR]) ? defaults[YEAR] : 0;
520
+ if (year === undefined || lodash_1.default.isNaN(year) || value) {
521
+ year = (defaults.length !== 3)
522
+ ? this.getDayWithHiddenFields(defaults).year
523
+ : (defaults[YEAR] && !lodash_1.default.isNaN(defaults[YEAR]) ? defaults[YEAR] : 0);
517
524
  }
518
525
  let result;
519
526
  if (!day && !month && !year) {
527
+ if (!isModalEditClosed) {
528
+ this.dataValue = this.emptyValue;
529
+ if (this.options.building) {
530
+ this.triggerChange();
531
+ }
532
+ }
520
533
  return null;
521
534
  }
522
535
  // add trailing zeros if the data is showed
@@ -571,6 +584,9 @@ class DayComponent extends Field_1.default {
571
584
  * @returns {string|null} - The string value of the date.
572
585
  */
573
586
  getValueAsString(value) {
587
+ if (!value) {
588
+ return '';
589
+ }
574
590
  return this.getDate(value) || '';
575
591
  }
576
592
  focus(field) {
@@ -13,6 +13,7 @@ const utils_1 = require("../../utils/utils");
13
13
  const EditRowState = {
14
14
  New: 'new',
15
15
  Editing: 'editing',
16
+ Saving: 'saving',
16
17
  Saved: 'saved',
17
18
  Viewing: 'viewing',
18
19
  Removed: 'removed',
@@ -808,6 +809,10 @@ class EditGridComponent extends NestedArrayComponent_1.default {
808
809
  if (!this.component.rowDrafts) {
809
810
  editRow.components.forEach((comp) => comp.setPristine(false));
810
811
  }
812
+ // Mark the row with a 'Saving' state to trigger validation for future row changes
813
+ if (editRow.state === EditRowState.New) {
814
+ editRow.state = EditRowState.Saving;
815
+ }
811
816
  const errors = this.validateRow(editRow, true);
812
817
  if (!this.component.rowDrafts) {
813
818
  if (errors.length) {
@@ -820,7 +825,7 @@ class EditGridComponent extends NestedArrayComponent_1.default {
820
825
  this.root.focusedComponent = null;
821
826
  }
822
827
  switch (editRow.state) {
823
- case EditRowState.New: {
828
+ case EditRowState.Saving: {
824
829
  const newIndex = dataValue.length;
825
830
  dataValue.push(editRow.data);
826
831
  editRow.components.forEach(component => component.rowIndex = newIndex);
@@ -980,7 +985,7 @@ class EditGridComponent extends NestedArrayComponent_1.default {
980
985
  }
981
986
  shouldValidateRow(editRow, dirty) {
982
987
  return this.shouldValidateDraft(editRow) ||
983
- editRow.state === EditRowState.New ||
988
+ editRow.state === EditRowState.Saving ||
984
989
  editRow.state === EditRowState.Editing ||
985
990
  editRow.alerts ||
986
991
  dirty;
@@ -1084,6 +1089,7 @@ class EditGridComponent extends NestedArrayComponent_1.default {
1084
1089
  }
1085
1090
  else if (errorContainer) {
1086
1091
  errorContainer.textContent = '';
1092
+ this.removeClass(errorContainer, 'help-block');
1087
1093
  }
1088
1094
  }
1089
1095
  }
@@ -79,6 +79,14 @@ class RadioComponent extends ListComponent_1.default {
79
79
  }
80
80
  return defaultValue;
81
81
  }
82
+ resetValue() {
83
+ this.unset();
84
+ this.setValue(this.emptyValue, {
85
+ noUpdateEvent: true,
86
+ noValidate: true,
87
+ resetValue: true
88
+ });
89
+ }
82
90
  get inputInfo() {
83
91
  var _a;
84
92
  const info = super.elementInfo();
@@ -246,7 +246,11 @@ class SelectComponent extends ListComponent_1.default {
246
246
  const value = (typeof itemLabel === 'string') ? this.t(itemLabel, { _userInput: true }) : itemLabel;
247
247
  return this.sanitize(value, this.shouldSanitizeValue);
248
248
  }
249
- if (this.component.multiple && lodash_1.default.isArray(this.dataValue) ? this.dataValue.find((val) => this.normalizeSingleValue(value) === val) : (this.dataValue === this.normalizeSingleValue(value))) {
249
+ // Inside DataTable component won't have dataValue set
250
+ const shouldUseSelectData = (this.component.multiple && lodash_1.default.isArray(this.dataValue)
251
+ ? this.dataValue.find((val) => this.normalizeSingleValue(value) === val)
252
+ : (this.dataValue === this.normalizeSingleValue(value))) || this.inDataTable;
253
+ if (shouldUseSelectData) {
250
254
  const selectData = this.selectData;
251
255
  if (selectData) {
252
256
  const templateValue = this.component.reference && (value === null || value === void 0 ? void 0 : value._id) ? value._id.toString() : value;
@@ -1213,7 +1217,7 @@ class SelectComponent extends ListComponent_1.default {
1213
1217
  // Check to see if we need to save off the template data into our metadata.
1214
1218
  const templateValue = this.component.reference && (value === null || value === void 0 ? void 0 : value._id) ? value._id.toString() : value;
1215
1219
  const shouldSaveData = !valueIsObject || this.component.reference;
1216
- if (templateValue && shouldSaveData && this.templateData && this.templateData[templateValue] && ((_a = this.root) === null || _a === void 0 ? void 0 : _a.submission)) {
1220
+ if (!lodash_1.default.isNil(templateValue) && shouldSaveData && this.templateData && this.templateData[templateValue] && ((_a = this.root) === null || _a === void 0 ? void 0 : _a.submission)) {
1217
1221
  const submission = this.root.submission;
1218
1222
  if (!submission.metadata) {
1219
1223
  submission.metadata = {};
@@ -1468,8 +1472,12 @@ class SelectComponent extends ListComponent_1.default {
1468
1472
  asString(value, options = {}) {
1469
1473
  var _a;
1470
1474
  value = value !== null && value !== void 0 ? value : this.getValue();
1471
- if (options.modalPreview) {
1472
- const template = this.itemTemplate(value, value);
1475
+ if (options.modalPreview || this.inDataTable) {
1476
+ if (this.inDataTable) {
1477
+ value = this.undoValueTyping(value);
1478
+ }
1479
+ const templateValue = (this.isEntireObjectDisplay() && !lodash_1.default.isObject(value.data)) ? { data: value } : value;
1480
+ const template = this.itemTemplate(templateValue, value, options);
1473
1481
  return template;
1474
1482
  }
1475
1483
  //need to convert values to strings to be able to compare values with available options that are strings
@@ -15,8 +15,8 @@ export const getComponentPath: typeof Utils.getComponentPath;
15
15
  export const isComponentNestedDataType: typeof Utils.isComponentNestedDataType;
16
16
  export const componentPath: typeof Utils.componentPath;
17
17
  export const componentChildPath: any;
18
- export const eachComponentDataAsync: (components: Component[], data: DataObject, fn: AsyncComponentDataCallback, path?: string | undefined, index?: number | undefined, parent?: any, includeAll?: boolean | undefined) => Promise<void>;
19
- export const eachComponentData: (components: Component[], data: DataObject, fn: ComponentDataCallback, path?: string | undefined, index?: number | undefined, parent?: any, includeAll?: boolean | undefined) => void;
18
+ export const eachComponentDataAsync: (components: Component[], data: DataObject, fn: EachComponentDataAsyncCallback, path?: string | undefined, index?: number | undefined, parent?: any, includeAll?: boolean | undefined) => Promise<void>;
19
+ export const eachComponentData: (components: Component[], data: DataObject, fn: EachComponentDataCallback, path?: string | undefined, index?: number | undefined, parent?: any, includeAll?: boolean | undefined) => void;
20
20
  export const getComponentKey: typeof Utils.getComponentKey;
21
21
  export const getContextualRowPath: typeof Utils.getContextualRowPath;
22
22
  export const getContextualRowData: typeof Utils.getContextualRowData;
@@ -1241,7 +1241,12 @@ export default class Webform extends NestedDataComponent {
1241
1241
  onChange(flags, changed, modified, changes) {
1242
1242
  flags = flags || {};
1243
1243
  let isChangeEventEmitted = false;
1244
- super.onChange(flags, true);
1244
+ if (this.parent?.subForm === this) {
1245
+ super.onChange({ ...flags, modified }, false);
1246
+ }
1247
+ else {
1248
+ super.onChange(flags, true);
1249
+ }
1245
1250
  const value = _.clone(this.submission);
1246
1251
  flags.changed = value.changed = changed;
1247
1252
  flags.changes = changes;
@@ -1,6 +1,7 @@
1
1
  import Component from './_classes/component/Component';
2
2
  import EditFormUtils from './_classes/component/editForm/utils';
3
3
  import BaseEditForm from './_classes/component/Component.form';
4
+ import { getComponentKey, getModelType } from '../utils/utils';
4
5
  import _ from 'lodash';
5
6
  export default class Components {
6
7
  static _editFormUtils = EditFormUtils;
@@ -52,7 +53,8 @@ export default class Components {
52
53
  */
53
54
  static getComponentPath(component) {
54
55
  let path = '';
55
- if (component.component.key) {
56
+ const componentKey = getComponentKey(component.component);
57
+ if (componentKey) {
56
58
  let thisPath = component.options?.parent || component;
57
59
  while (thisPath && !thisPath.allowData && thisPath.parent) {
58
60
  thisPath = thisPath.parent;
@@ -64,7 +66,10 @@ export default class Components {
64
66
  const rowIndex = component.row;
65
67
  const rowIndexPath = rowIndex && !['container'].includes(thisPath.component.type) ? `[${Number.parseInt(rowIndex)}]` : '';
66
68
  path = `${thisPath.path}${rowIndexPath}.`;
67
- path += component.component.key;
69
+ if (rowIndexPath && getModelType(thisPath) === 'nestedDataArray') {
70
+ path = `${path}data.`;
71
+ }
72
+ path += componentKey;
68
73
  return _.trim(path, '.');
69
74
  }
70
75
  return path;
@@ -1720,12 +1720,12 @@ export default class Component extends Element {
1720
1720
  restoreCaretPosition() {
1721
1721
  if (this.root?.currentSelection) {
1722
1722
  if (this.refs.input?.length) {
1723
- const { selection, index } = this.root.currentSelection;
1723
+ const { index } = this.root.currentSelection;
1724
1724
  let input = this.refs.input[index];
1725
1725
  const isInputRangeSelectable = (i) => /text|search|password|tel|url/i.test(i?.type || '');
1726
1726
  if (input) {
1727
1727
  if (isInputRangeSelectable(input)) {
1728
- input.setSelectionRange(...selection);
1728
+ input.setSelectionRange(input.value.length, input.value.length);
1729
1729
  }
1730
1730
  }
1731
1731
  else {
@@ -2930,7 +2930,7 @@ export default class Component extends Element {
2930
2930
  flags.dirty = true;
2931
2931
  }
2932
2932
  if (flags.fromSubmission && this.hasValue(data)) {
2933
- flags.dirty = true;
2933
+ flags.dirty = this.pristine && this.component.protected ? false : true;
2934
2934
  }
2935
2935
  this.setDirty(flags.dirty);
2936
2936
  return this.setComponentValidity(errors, flags.dirty, flags.silentCheck, flags.fromSubmission);
@@ -2956,6 +2956,7 @@ export default class Component extends Element {
2956
2956
  value: this.validationValue,
2957
2957
  path: this.path || this.component.key,
2958
2958
  instance: this,
2959
+ form: this.root ? this.root._form : {},
2959
2960
  scope: { errors: [] },
2960
2961
  processors: [
2961
2962
  validateProcessInfo
@@ -3433,7 +3434,9 @@ export default class Component extends Element {
3433
3434
  if ('beforeFocus' in this.parent) {
3434
3435
  this.parent.beforeFocus(this);
3435
3436
  }
3436
- index = index || this.refs.input?.length - 1;
3437
+ if (!index && !_.isNumber(index) && this.refs?.input?.length) {
3438
+ index = this.refs.input.length - 1;
3439
+ }
3437
3440
  if (this.refs.input?.length) {
3438
3441
  const focusingInput = this.refs.input[index];
3439
3442
  if (this.component.widget?.type === 'calendar') {
@@ -185,6 +185,7 @@ export default class ListComponent extends Field {
185
185
  return;
186
186
  }
187
187
  let { url } = this.component.data;
188
+ url = _.trim(url);
188
189
  let method;
189
190
  let body;
190
191
  if (url.startsWith('/')) {
@@ -210,6 +210,16 @@ export default class AddressComponent extends ContainerComponent {
210
210
  isValueInLegacyFormat(value) {
211
211
  return value && !value.mode;
212
212
  }
213
+ set dataValue(value) {
214
+ super.dataValue = value;
215
+ }
216
+ get dataValue() {
217
+ const resultValue = _.get(this._data, this.component.path);
218
+ if (!_.isArray(resultValue) && this.component.multiple) {
219
+ return [resultValue];
220
+ }
221
+ return super.dataValue;
222
+ }
213
223
  normalizeValue(value) {
214
224
  return (this.manualModeEnabled && this.isValueInLegacyFormat(value))
215
225
  ? {
@@ -284,7 +284,7 @@ export default class DayComponent extends Field {
284
284
  if (!this.component.fields.day.hide && maxDay) {
285
285
  this.refs.day.max = maxDay;
286
286
  }
287
- if (maxDay && day > maxDay) {
287
+ if (maxDay && day > maxDay && this.refs.day) {
288
288
  this.refs.day.value = this.refs.day.max;
289
289
  }
290
290
  updateValueAndSaveFocus(this.refs.month, 'month')();
@@ -494,27 +494,40 @@ export default class DayComponent extends Field {
494
494
  if (defaultValue) {
495
495
  defaults = defaultValue.split('/').map(x => parseInt(x, 10));
496
496
  }
497
+ const isModalEditClosed = this.component.modalEdit && !this.componentModal.isOpened;
497
498
  if (this.showDay && this.refs.day) {
498
- day = parseInt(this.refs.day.value, 10);
499
+ day = (this.refs.day.value === '' && !isModalEditClosed) ? '' : parseInt(this.refs.day.value, 10);
499
500
  }
500
- if (day === undefined || _.isNaN(day)) {
501
- day = defaults[DAY] && !_.isNaN(defaults[DAY]) ? defaults[DAY] : 0;
501
+ if (day === undefined || _.isNaN(day) || value) {
502
+ day = (defaults.length !== 3)
503
+ ? this.getDayWithHiddenFields(defaults).day
504
+ : (defaults[DAY] && !_.isNaN(defaults[DAY]) ? defaults[DAY] : 0);
502
505
  }
503
506
  if (this.showMonth && this.refs.month) {
504
507
  // Months are 0 indexed.
505
- month = parseInt(this.refs.month.value, 10);
508
+ month = (this.refs.month.value === '' && !isModalEditClosed) ? '' : parseInt(this.refs.month.value, 10);
506
509
  }
507
- if (month === undefined || _.isNaN(month)) {
508
- month = defaults[MONTH] && !_.isNaN(defaults[MONTH]) ? defaults[MONTH] : 0;
510
+ if (month === undefined || _.isNaN(month) || value) {
511
+ month = (defaults.length !== 3)
512
+ ? this.getDayWithHiddenFields(defaults).month
513
+ : (defaults[MONTH] && !_.isNaN(defaults[MONTH]) ? defaults[MONTH] : 0);
509
514
  }
510
515
  if (this.showYear && this.refs.year) {
511
- year = parseInt(this.refs.year.value);
516
+ year = (this.refs.year.value === '' && !isModalEditClosed) ? '' : parseInt(this.refs.year.value);
512
517
  }
513
- if (year === undefined || _.isNaN(year)) {
514
- year = defaults[YEAR] && !_.isNaN(defaults[YEAR]) ? defaults[YEAR] : 0;
518
+ if (year === undefined || _.isNaN(year) || value) {
519
+ year = (defaults.length !== 3)
520
+ ? this.getDayWithHiddenFields(defaults).year
521
+ : (defaults[YEAR] && !_.isNaN(defaults[YEAR]) ? defaults[YEAR] : 0);
515
522
  }
516
523
  let result;
517
524
  if (!day && !month && !year) {
525
+ if (!isModalEditClosed) {
526
+ this.dataValue = this.emptyValue;
527
+ if (this.options.building) {
528
+ this.triggerChange();
529
+ }
530
+ }
518
531
  return null;
519
532
  }
520
533
  // add trailing zeros if the data is showed
@@ -569,6 +582,9 @@ export default class DayComponent extends Field {
569
582
  * @returns {string|null} - The string value of the date.
570
583
  */
571
584
  getValueAsString(value) {
585
+ if (!value) {
586
+ return '';
587
+ }
572
588
  return this.getDate(value) || '';
573
589
  }
574
590
  focus(field) {
@@ -8,6 +8,7 @@ import { fastCloneDeep, Evaluator, getArrayFromComponentPath, eachComponent } fr
8
8
  const EditRowState = {
9
9
  New: 'new',
10
10
  Editing: 'editing',
11
+ Saving: 'saving',
11
12
  Saved: 'saved',
12
13
  Viewing: 'viewing',
13
14
  Removed: 'removed',
@@ -798,6 +799,10 @@ export default class EditGridComponent extends NestedArrayComponent {
798
799
  if (!this.component.rowDrafts) {
799
800
  editRow.components.forEach((comp) => comp.setPristine(false));
800
801
  }
802
+ // Mark the row with a 'Saving' state to trigger validation for future row changes
803
+ if (editRow.state === EditRowState.New) {
804
+ editRow.state = EditRowState.Saving;
805
+ }
801
806
  const errors = this.validateRow(editRow, true);
802
807
  if (!this.component.rowDrafts) {
803
808
  if (errors.length) {
@@ -810,7 +815,7 @@ export default class EditGridComponent extends NestedArrayComponent {
810
815
  this.root.focusedComponent = null;
811
816
  }
812
817
  switch (editRow.state) {
813
- case EditRowState.New: {
818
+ case EditRowState.Saving: {
814
819
  const newIndex = dataValue.length;
815
820
  dataValue.push(editRow.data);
816
821
  editRow.components.forEach(component => component.rowIndex = newIndex);
@@ -970,7 +975,7 @@ export default class EditGridComponent extends NestedArrayComponent {
970
975
  }
971
976
  shouldValidateRow(editRow, dirty) {
972
977
  return this.shouldValidateDraft(editRow) ||
973
- editRow.state === EditRowState.New ||
978
+ editRow.state === EditRowState.Saving ||
974
979
  editRow.state === EditRowState.Editing ||
975
980
  editRow.alerts ||
976
981
  dirty;
@@ -1072,6 +1077,7 @@ export default class EditGridComponent extends NestedArrayComponent {
1072
1077
  }
1073
1078
  else if (errorContainer) {
1074
1079
  errorContainer.textContent = '';
1080
+ this.removeClass(errorContainer, 'help-block');
1075
1081
  }
1076
1082
  }
1077
1083
  }
@@ -80,6 +80,14 @@ export default class RadioComponent extends ListComponent {
80
80
  }
81
81
  return defaultValue;
82
82
  }
83
+ resetValue() {
84
+ this.unset();
85
+ this.setValue(this.emptyValue, {
86
+ noUpdateEvent: true,
87
+ noValidate: true,
88
+ resetValue: true
89
+ });
90
+ }
83
91
  get inputInfo() {
84
92
  const info = super.elementInfo();
85
93
  info.type = 'input';
@@ -246,7 +246,11 @@ export default class SelectComponent extends ListComponent {
246
246
  const value = (typeof itemLabel === 'string') ? this.t(itemLabel, { _userInput: true }) : itemLabel;
247
247
  return this.sanitize(value, this.shouldSanitizeValue);
248
248
  }
249
- if (this.component.multiple && _.isArray(this.dataValue) ? this.dataValue.find((val) => this.normalizeSingleValue(value) === val) : (this.dataValue === this.normalizeSingleValue(value))) {
249
+ // Inside DataTable component won't have dataValue set
250
+ const shouldUseSelectData = (this.component.multiple && _.isArray(this.dataValue)
251
+ ? this.dataValue.find((val) => this.normalizeSingleValue(value) === val)
252
+ : (this.dataValue === this.normalizeSingleValue(value))) || this.inDataTable;
253
+ if (shouldUseSelectData) {
250
254
  const selectData = this.selectData;
251
255
  if (selectData) {
252
256
  const templateValue = this.component.reference && value?._id ? value._id.toString() : value;
@@ -1241,7 +1245,7 @@ export default class SelectComponent extends ListComponent {
1241
1245
  // Check to see if we need to save off the template data into our metadata.
1242
1246
  const templateValue = this.component.reference && value?._id ? value._id.toString() : value;
1243
1247
  const shouldSaveData = !valueIsObject || this.component.reference;
1244
- if (templateValue && shouldSaveData && this.templateData && this.templateData[templateValue] && this.root?.submission) {
1248
+ if (!_.isNil(templateValue) && shouldSaveData && this.templateData && this.templateData[templateValue] && this.root?.submission) {
1245
1249
  const submission = this.root.submission;
1246
1250
  if (!submission.metadata) {
1247
1251
  submission.metadata = {};
@@ -1495,8 +1499,12 @@ export default class SelectComponent extends ListComponent {
1495
1499
  }
1496
1500
  asString(value, options = {}) {
1497
1501
  value = value ?? this.getValue();
1498
- if (options.modalPreview) {
1499
- const template = this.itemTemplate(value, value);
1502
+ if (options.modalPreview || this.inDataTable) {
1503
+ if (this.inDataTable) {
1504
+ value = this.undoValueTyping(value);
1505
+ }
1506
+ const templateValue = (this.isEntireObjectDisplay() && !_.isObject(value.data)) ? { data: value } : value;
1507
+ const template = this.itemTemplate(templateValue, value, options);
1500
1508
  return template;
1501
1509
  }
1502
1510
  //need to convert values to strings to be able to compare values with available options that are strings
@@ -15,8 +15,8 @@ export const getComponentPath: typeof Utils.getComponentPath;
15
15
  export const isComponentNestedDataType: typeof Utils.isComponentNestedDataType;
16
16
  export const componentPath: typeof Utils.componentPath;
17
17
  export const componentChildPath: any;
18
- export const eachComponentDataAsync: (components: Component[], data: DataObject, fn: AsyncComponentDataCallback, path?: string | undefined, index?: number | undefined, parent?: any, includeAll?: boolean | undefined) => Promise<void>;
19
- export const eachComponentData: (components: Component[], data: DataObject, fn: ComponentDataCallback, path?: string | undefined, index?: number | undefined, parent?: any, includeAll?: boolean | undefined) => void;
18
+ export const eachComponentDataAsync: (components: Component[], data: DataObject, fn: EachComponentDataAsyncCallback, path?: string | undefined, index?: number | undefined, parent?: any, includeAll?: boolean | undefined) => Promise<void>;
19
+ export const eachComponentData: (components: Component[], data: DataObject, fn: EachComponentDataCallback, path?: string | undefined, index?: number | undefined, parent?: any, includeAll?: boolean | undefined) => void;
20
20
  export const getComponentKey: typeof Utils.getComponentKey;
21
21
  export const getContextualRowPath: typeof Utils.getContextualRowPath;
22
22
  export const getContextualRowData: typeof Utils.getContextualRowData;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@formio/js",
3
- "version": "5.0.0-dev.5834.98680ce",
3
+ "version": "5.0.0-dev.5834.b72f609",
4
4
  "description": "JavaScript powered Forms with JSON Form Builder",
5
5
  "main": "lib/cjs/index.js",
6
6
  "exports": {
@@ -82,7 +82,7 @@
82
82
  "dependencies": {
83
83
  "@formio/bootstrap": "3.0.0-dev.98.17ba6ea",
84
84
  "@formio/choices.js": "^10.2.1",
85
- "@formio/core": "v2.1.0-dev.160.d45b496",
85
+ "@formio/core": "2.3.0-dev.160.cabaa43",
86
86
  "@formio/text-mask-addons": "^3.8.0-formio.2",
87
87
  "@formio/vanilla-text-mask": "^5.1.1-formio.1",
88
88
  "abortcontroller-polyfill": "^1.7.5",