@formio/js 5.0.0-rc.43 → 5.0.0-rc.44

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. package/dist/formio.embed.js +1 -1
  2. package/dist/formio.embed.min.js +1 -1
  3. package/dist/formio.embed.min.js.LICENSE.txt +1 -1
  4. package/dist/formio.form.js +602 -580
  5. package/dist/formio.form.min.js +1 -1
  6. package/dist/formio.form.min.js.LICENSE.txt +1 -11
  7. package/dist/formio.full.js +605 -583
  8. package/dist/formio.full.min.js +1 -1
  9. package/dist/formio.full.min.js.LICENSE.txt +1 -11
  10. package/dist/formio.js +10 -11
  11. package/dist/formio.min.js +1 -1
  12. package/dist/formio.min.js.LICENSE.txt +1 -1
  13. package/dist/formio.utils.js +1 -1
  14. package/dist/formio.utils.min.js +1 -1
  15. package/dist/formio.utils.min.js.LICENSE.txt +1 -1
  16. package/lib/cjs/Element.js +2 -0
  17. package/lib/cjs/Form.js +3 -1
  18. package/lib/cjs/Webform.js +93 -15
  19. package/lib/cjs/WebformBuilder.js +8 -8
  20. package/lib/cjs/components/_classes/component/Component.js +25 -8
  21. package/lib/cjs/components/_classes/componentModal/ComponentModal.js +5 -4
  22. package/lib/cjs/components/_classes/input/Input.js +1 -1
  23. package/lib/cjs/components/_classes/multivalue/Multivalue.js +1 -1
  24. package/lib/cjs/components/_classes/nested/NestedComponent.js +4 -2
  25. package/lib/cjs/components/datagrid/DataGrid.js +1 -1
  26. package/lib/cjs/components/editgrid/EditGrid.js +3 -3
  27. package/lib/cjs/components/form/Form.js +1 -1
  28. package/lib/cjs/components/html/HTML.js +2 -2
  29. package/lib/cjs/components/html/fixtures/comp3.js +40 -0
  30. package/lib/cjs/components/html/fixtures/index.js +3 -1
  31. package/lib/cjs/components/radio/Radio.js +29 -10
  32. package/lib/cjs/components/radio/editForm/Radio.edit.data.js +20 -0
  33. package/lib/cjs/components/radio/fixtures/comp11.js +85 -0
  34. package/lib/cjs/components/radio/fixtures/index.js +3 -1
  35. package/lib/cjs/components/select/Select.js +3 -0
  36. package/lib/cjs/components/select/editForm/Select.edit.data.js +63 -1
  37. package/lib/cjs/components/signature/Signature.js +1 -1
  38. package/lib/cjs/components/textarea/TextArea.js +1 -1
  39. package/lib/cjs/formio.form.js +5 -1
  40. package/lib/cjs/providers/storage/s3.js +29 -1
  41. package/lib/mjs/Element.js +2 -0
  42. package/lib/mjs/Form.js +3 -1
  43. package/lib/mjs/Webform.js +98 -16
  44. package/lib/mjs/WebformBuilder.js +8 -8
  45. package/lib/mjs/components/_classes/component/Component.js +25 -8
  46. package/lib/mjs/components/_classes/componentModal/ComponentModal.js +5 -4
  47. package/lib/mjs/components/_classes/input/Input.js +1 -1
  48. package/lib/mjs/components/_classes/multivalue/Multivalue.js +1 -1
  49. package/lib/mjs/components/_classes/nested/NestedComponent.js +4 -2
  50. package/lib/mjs/components/datagrid/DataGrid.js +1 -1
  51. package/lib/mjs/components/editgrid/EditGrid.js +3 -3
  52. package/lib/mjs/components/form/Form.js +1 -1
  53. package/lib/mjs/components/html/HTML.js +2 -2
  54. package/lib/mjs/components/html/fixtures/comp3.js +38 -0
  55. package/lib/mjs/components/html/fixtures/index.js +2 -1
  56. package/lib/mjs/components/radio/Radio.js +29 -10
  57. package/lib/mjs/components/radio/editForm/Radio.edit.data.js +20 -0
  58. package/lib/mjs/components/radio/fixtures/comp11.js +83 -0
  59. package/lib/mjs/components/radio/fixtures/index.js +2 -1
  60. package/lib/mjs/components/select/Select.js +3 -0
  61. package/lib/mjs/components/select/editForm/Select.edit.data.js +59 -1
  62. package/lib/mjs/components/signature/Signature.js +1 -1
  63. package/lib/mjs/components/textarea/TextArea.js +1 -1
  64. package/lib/mjs/formio.form.js +3 -1
  65. package/lib/mjs/providers/storage/s3.js +6 -1
  66. package/package.json +7 -8
  67. package/types/builders.d.ts +0 -7
  68. package/types/components/_classes/component/component.d.ts +0 -175
  69. package/types/components/_classes/componentmodal/componentmodal.d.ts +0 -31
  70. package/types/components/_classes/field/field.d.ts +0 -5
  71. package/types/components/_classes/input/input.d.ts +0 -30
  72. package/types/components/_classes/multivalue/multivalue.d.ts +0 -16
  73. package/types/components/_classes/nested/nestedComponent.d.ts +0 -61
  74. package/types/components/_classes/widgetcomponent/widgetComponent.d.ts +0 -6
  75. package/types/components/components.d.ts +0 -69
  76. package/types/components/schema.d.ts +0 -174
  77. package/types/displays.d.ts +0 -7
  78. package/types/element.d.ts +0 -45
  79. package/types/eventEmitter.d.ts +0 -3
  80. package/types/form.d.ts +0 -18
  81. package/types/formbuilder.d.ts +0 -6
  82. package/types/formio.d.ts +0 -1236
  83. package/types/index.d.ts +0 -18
  84. package/types/licenses.d.ts +0 -7
  85. package/types/providers.d.ts +0 -8
  86. package/types/rulesEngine/conjunctions.d.ts +0 -7
  87. package/types/rulesEngine/operators.d.ts +0 -7
  88. package/types/rulesEngine/quckRules.d.ts +0 -7
  89. package/types/rulesEngine/rules.d.ts +0 -7
  90. package/types/rulesEngine/transformers.d.ts +0 -7
  91. package/types/rulesEngine/valueSources.d.ts +0 -7
  92. package/types/templates.d.ts +0 -8
  93. package/types/utils.d.ts +0 -157
  94. package/types/widgets.d.ts +0 -4
@@ -12,7 +12,7 @@
12
12
 
13
13
  /*! @license DOMPurify 3.1.0 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.1.0/LICENSE */
14
14
 
15
- /*! formiojs v5.0.0-rc.43 | https://unpkg.com/formiojs@5.0.0-rc.43/LICENSE.txt */
15
+ /*! formiojs v5.0.0-rc.44 | https://unpkg.com/formiojs@5.0.0-rc.44/LICENSE.txt */
16
16
 
17
17
  /**
18
18
  * @license
@@ -98,6 +98,8 @@ class Element {
98
98
  *
99
99
  * @param {string} event - The event you wish to register the handler for.
100
100
  * @param {function} cb - The callback handler to handle this event.
101
+ * @param {boolean} [internal] - This is an internal event handler.
102
+ * @param {boolean} [once] - This event should only fire once.
101
103
  */
102
104
  on(event, cb, internal, once = false) {
103
105
  if (!this.events) {
package/lib/cjs/Form.js CHANGED
@@ -125,7 +125,9 @@ class Form extends Element_1.default {
125
125
  this.element.appendChild(this.loader);
126
126
  }
127
127
  else if (this.loader) {
128
- this.element.removeChild(this.loader);
128
+ if (this.element.contains(this.loader)) {
129
+ this.element.removeChild(this.loader);
130
+ }
129
131
  this.loader = null;
130
132
  }
131
133
  }
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const lodash_1 = __importDefault(require("lodash"));
7
7
  const moment_1 = __importDefault(require("moment"));
8
8
  const compare_versions_1 = require("compare-versions");
9
+ const core_1 = require("@formio/core");
9
10
  const EventEmitter_1 = __importDefault(require("./EventEmitter"));
10
11
  const i18n_1 = __importDefault(require("./i18n"));
11
12
  const Formio_1 = require("./Formio");
@@ -39,6 +40,89 @@ function getOptions(options) {
39
40
  }
40
41
  return options;
41
42
  }
43
+ /**
44
+ * Represents a JSON value.
45
+ * @typedef {(string | number | boolean | null | JSONArray | JSONObject)} JSON
46
+ */
47
+ /**
48
+ * Represents a JSON array.
49
+ * @typedef {Array<JSON>} JSONArray
50
+ */
51
+ /**
52
+ * Represents a JSON object.
53
+ * @typedef {{[key: string]: JSON}} JSONObject
54
+ */
55
+ /**
56
+ * @typedef {Object} FormioHooks
57
+ * @property {function} [beforeSubmit]
58
+ * @property {function} [beforeCancel]
59
+ * @property {function} [beforeNext]
60
+ * @property {function} [beforePrev]
61
+ * @property {function} [attachComponent]
62
+ * @property {function} [setDataValue]
63
+ * @property {function} [addComponents]
64
+ * @property {function} [addComponent]
65
+ * @property {function} [customValidation]
66
+ * @property {function} [attachWebform]
67
+ */
68
+ /**
69
+ * @typedef {Object} SanitizeConfig
70
+ * @property {string[]} [addAttr]
71
+ * @property {string[]} [addTags]
72
+ * @property {string[]} [allowedAttrs]
73
+ * @property {string[]} [allowedTags]
74
+ * @property {string[]} [allowedUriRegex]
75
+ * @property {string[]} [addUriSafeAttr]
76
+ */
77
+ /**
78
+ * @typedef {Object} ButtonSettings
79
+ * @property {boolean} [showPrevious]
80
+ * @property {boolean} [showNext]
81
+ * @property {boolean} [showCancel]
82
+ * @property {boolean} [showSubmit]
83
+ */
84
+ /**
85
+ * @typedef {Object} FormOptions
86
+ * @property {boolean} [saveDraft] - Enable the save draft feature.
87
+ * @property {number} [saveDraftThrottle] - The throttle for the save draft feature.
88
+ * @property {boolean} [readOnly] - Set this form to readOnly.
89
+ * @property {boolean} [noAlerts] - Disable the alerts dialog.
90
+ * @property {{[key: string]: string}} [i18n] - The translation file for this rendering.
91
+ * @property {string} [template] - Custom logic for creation of elements.
92
+ * @property {boolean} [noDefaults] - Exclude default values from the settings.
93
+ * @property {any} [fileService] - The file service for this form.
94
+ * @property {EventEmitter} [events] - The EventEmitter for this form.
95
+ * @property {string} [language] - The language to render this form in.
96
+ * @property {{[key: string]: string}} [i18next] - The i18next configuration for this form.
97
+ * @property {boolean} [viewAsHtml] - View the form as raw HTML.
98
+ * @property {'form' | 'html' | 'flat' | 'builder' | 'pdf'} [renderMode] - The render mode for this form.
99
+ * @property {boolean} [highlightErrors] - Highlight any errors on the form.
100
+ * @property {string} [componentErrorClass] - The error class for components.
101
+ * @property {any} [templates] - The templates for this form.
102
+ * @property {string} [iconset] - The iconset for this form.
103
+ * @property {Component[]} [components] - The components for this form.
104
+ * @property {{[key: string]: boolean}} [disabled] - Disabled components for this form.
105
+ * @property {boolean} [showHiddenFields] - Show hidden fields.
106
+ * @property {{[key: string]: boolean}} [hide] - Hidden components for this form.
107
+ * @property {{[key: string]: boolean}} [show] - Components to show for this form.
108
+ * @property {Formio} [formio] - The Formio instance for this form.
109
+ * @property {string} [decimalSeparator] - The decimal separator for this form.
110
+ * @property {string} [thousandsSeparator] - The thousands separator for this form.
111
+ * @property {FormioHooks} [hooks] - The hooks for this form.
112
+ * @property {boolean} [alwaysDirty] - Always be dirty.
113
+ * @property {boolean} [skipDraftRestore] - Skip restoring a draft.
114
+ * @property {'form' | 'wizard' | 'pdf'} [display] - The display for this form.
115
+ * @property {string} [cdnUrl] - The CDN url for this form.
116
+ * @property {boolean} [flatten] - Flatten the form.
117
+ * @property {boolean} [sanitize] - Sanitize the form.
118
+ * @property {SanitizeConfig} [sanitizeConfig] - The sanitize configuration for this form.
119
+ * @property {ButtonSettings} [buttonSettings] - The button settings for this form.
120
+ * @property {Object} [breadCrumbSettings] - The breadcrumb settings for this form.
121
+ * @property {boolean} [allowPrevious] - Allow the previous button (for Wizard forms).
122
+ * @property {string[]} [wizardButtonOrder] - The order of the buttons (for Wizard forms).
123
+ * @property {boolean} [showCheckboxBackground] - Show the checkbox background.
124
+ * @property {number} [zoom] - The zoom for PDF forms.
125
+ */
42
126
  /**
43
127
  * Renders a Form.io form within the webpage.
44
128
  */
@@ -46,25 +130,19 @@ class Webform extends NestedDataComponent_1.default {
46
130
  /**
47
131
  * Creates a new Form instance.
48
132
  *
49
- * @param {Object} options - The options to create a new form instance.
50
- * @param {boolean} options.saveDraft - Set this if you would like to enable the save draft feature.
51
- * @param {boolean} options.saveDraftThrottle - The throttle for the save draft feature.
52
- * @param {boolean} options.readOnly - Set this form to readOnly
53
- * @param {boolean} options.noAlerts - Set to true to disable the alerts dialog.
54
- * @param {boolean} options.i18n - The translation file for this rendering. @see https://github.com/formio/formio.js/blob/master/i18n.js
55
- * @param {boolean} options.template - Provides a way to inject custom logic into the creation of every element rendered within the form.
133
+ * @param {HTMLElement | Object | FormOptions} [elementOrOptions] - The DOM element to render this form within or the options to create this form instance.
134
+ * @param {FormOptions} [options] - The options to create a new form instance.
56
135
  */
57
- /* eslint-disable max-statements */
58
- constructor() {
59
- let element, options;
60
- if (arguments[0] instanceof HTMLElement || arguments[1]) {
61
- element = arguments[0];
62
- options = arguments[1];
136
+ constructor(elementOrOptions, options) {
137
+ let element, formOptions;
138
+ if (elementOrOptions instanceof HTMLElement || options) {
139
+ element = elementOrOptions;
140
+ formOptions = options;
63
141
  }
64
142
  else {
65
- options = arguments[0];
143
+ formOptions = elementOrOptions;
66
144
  }
67
- super(null, getOptions(options));
145
+ super(null, getOptions(formOptions));
68
146
  this.executeShortcuts = (event) => {
69
147
  const { target } = event;
70
148
  if (!this.keyboardCatchableElement(target)) {
@@ -178,7 +178,7 @@ class WebformBuilder extends Component_1.default {
178
178
  return element;
179
179
  }
180
180
  // Attach container and component to element for later reference.
181
- const containerElement = element.querySelector(`[ref="${component.component.key}-container"]`) || element;
181
+ const containerElement = element.querySelector(`[${this._referenceAttributeName}="${component.component.key}-container"]`) || element;
182
182
  containerElement.formioContainer = container;
183
183
  containerElement.formioComponent = component;
184
184
  // Add container to draggable list.
@@ -1025,7 +1025,7 @@ class WebformBuilder extends Component_1.default {
1025
1025
  };
1026
1026
  const fieldsToRemoveDoubleQuotes = ['label', 'tooltip'];
1027
1027
  this.preview.form.components.forEach(component => this.replaceDoubleQuotes(component, fieldsToRemoveDoubleQuotes));
1028
- const previewElement = this.componentEdit.querySelector('[ref="preview"]');
1028
+ const previewElement = this.componentEdit.querySelector(`[${this._referenceAttributeName}="preview"]`);
1029
1029
  if (previewElement) {
1030
1030
  this.setContent(previewElement, this.preview.render(), null, sanitizeConfig);
1031
1031
  this.preview.attach(previewElement);
@@ -1193,7 +1193,7 @@ class WebformBuilder extends Component_1.default {
1193
1193
  this.emit('saveComponent', schema, originalComp, parentComponentSchema, path, index, isNew, originalComponentSchema);
1194
1194
  }
1195
1195
  attachEditComponentControls(component, parent, isNew, original, ComponentClass) {
1196
- const cancelButtons = this.componentEdit.querySelectorAll('[ref="cancelButton"]');
1196
+ const cancelButtons = this.componentEdit.querySelectorAll(`[${this._referenceAttributeName}="cancelButton"]`);
1197
1197
  cancelButtons.forEach((cancelButton) => {
1198
1198
  this.editForm.addEventListener(cancelButton, 'click', (event) => {
1199
1199
  event.preventDefault();
@@ -1203,7 +1203,7 @@ class WebformBuilder extends Component_1.default {
1203
1203
  this.highlightInvalidComponents();
1204
1204
  });
1205
1205
  });
1206
- const removeButtons = this.componentEdit.querySelectorAll('[ref="removeButton"]');
1206
+ const removeButtons = this.componentEdit.querySelectorAll(`[${this._referenceAttributeName}="removeButton"]`);
1207
1207
  removeButtons.forEach((removeButton) => {
1208
1208
  this.editForm.addEventListener(removeButton, 'click', (event) => {
1209
1209
  event.preventDefault();
@@ -1215,7 +1215,7 @@ class WebformBuilder extends Component_1.default {
1215
1215
  this.highlightInvalidComponents();
1216
1216
  });
1217
1217
  });
1218
- const saveButtons = this.componentEdit.querySelectorAll('[ref="saveButton"]');
1218
+ const saveButtons = this.componentEdit.querySelectorAll(`[${this._referenceAttributeName}="saveButton"]`);
1219
1219
  saveButtons.forEach((saveButton) => {
1220
1220
  this.editForm.addEventListener(saveButton, 'click', (event) => {
1221
1221
  event.preventDefault();
@@ -1231,7 +1231,7 @@ class WebformBuilder extends Component_1.default {
1231
1231
  this.saveComponent(component, parent, isNew, original);
1232
1232
  });
1233
1233
  });
1234
- const previewButtons = this.componentEdit.querySelectorAll('[ref="previewButton"]');
1234
+ const previewButtons = this.componentEdit.querySelectorAll(`[${this._referenceAttributeName}="previewButton"]`);
1235
1235
  previewButtons.forEach((previewButton) => {
1236
1236
  this.editForm.addEventListener(previewButton, 'click', (event) => {
1237
1237
  event.preventDefault();
@@ -1244,7 +1244,7 @@ class WebformBuilder extends Component_1.default {
1244
1244
  showPreview: this.showPreview,
1245
1245
  helplinks: this.helplinks,
1246
1246
  }));
1247
- this.editForm.attach(this.componentEdit.querySelector('[ref="editForm"]'));
1247
+ this.editForm.attach(this.componentEdit.querySelector(`[${this._referenceAttributeName}="editForm"]`));
1248
1248
  this.attachEditComponentControls(component, parent, isNew, original, ComponentClass);
1249
1249
  });
1250
1250
  });
@@ -1336,7 +1336,7 @@ class WebformBuilder extends Component_1.default {
1336
1336
  }));
1337
1337
  this.dialog = this.createModal(this.componentEdit, lodash_1.default.get(this.options, 'dialogAttr', {}));
1338
1338
  // This is the attach step.
1339
- this.editForm.attach(this.componentEdit.querySelector('[ref="editForm"]'));
1339
+ this.editForm.attach(this.componentEdit.querySelector(`[${this._referenceAttributeName}="editForm"]`));
1340
1340
  this.hook('editFormWrapper');
1341
1341
  this.updateComponent(componentCopy);
1342
1342
  this.editForm.on('change', (event) => {
@@ -354,6 +354,10 @@ class Component extends Element_1.default {
354
354
  this._parentVisible = this.options.hasOwnProperty('parentVisible') ? this.options.parentVisible : true;
355
355
  this._visible = this._parentVisible && this.conditionallyVisible(null, data);
356
356
  this._parentDisabled = false;
357
+ /**
358
+ * The reference attribute name for this component
359
+ */
360
+ this._referenceAttributeName = 'ref';
357
361
  /**
358
362
  * Used to trigger a new change in this component.
359
363
  * @type {function} - Call to trigger a change in this component.
@@ -809,21 +813,22 @@ class Component extends Element_1.default {
809
813
  const name = names[names.length - 1];
810
814
  const templatesByName = Templates_1.default.defaultTemplates[name];
811
815
  if (!templatesByName) {
812
- return `Unknown template: ${name}`;
816
+ return { template: `Unknown template: ${name}` };
813
817
  }
814
818
  const templateByMode = this.checkTemplateMode(templatesByName, modes);
815
819
  if (templateByMode) {
816
- return templateByMode;
820
+ return { template: templateByMode };
817
821
  }
818
- return templatesByName.form;
822
+ return { template: templatesByName.form };
819
823
  }
820
824
  checkTemplate(templates, names, modes) {
821
825
  for (const name of names) {
822
826
  const templatesByName = templates[name];
823
827
  if (templatesByName) {
828
+ const { referenceAttributeName } = templatesByName;
824
829
  const templateByMode = this.checkTemplateMode(templatesByName, modes);
825
830
  if (templateByMode) {
826
- return templateByMode;
831
+ return { template: templateByMode, referenceAttributeName };
827
832
  }
828
833
  }
829
834
  }
@@ -880,7 +885,11 @@ class Component extends Element_1.default {
880
885
  `${name}`,
881
886
  ];
882
887
  // Allow template alters.
883
- return this.hook(`render${name.charAt(0).toUpperCase() + name.substring(1, name.length)}`, this.interpolate(this.getTemplate(names, mode), data), data, mode);
888
+ const { referenceAttributeName, template } = this.getTemplate(names, mode);
889
+ if (referenceAttributeName) {
890
+ this._referenceAttributeName = referenceAttributeName;
891
+ }
892
+ return this.hook(`render${name.charAt(0).toUpperCase() + name.substring(1, name.length)}`, this.interpolate(template, data), data, mode);
884
893
  }
885
894
  /**
886
895
  * Sanitize an html string.
@@ -996,11 +1005,19 @@ class Component extends Element_1.default {
996
1005
  // Return current timezone if none are provided.
997
1006
  return (0, utils_1.currentTimezone)();
998
1007
  }
999
- loadRefs(element, refs) {
1008
+ /**
1009
+ *
1010
+ * @param {HTMLElement} element - The containing DOM element to query for the ref value.
1011
+ * @param {object} refs - The references to load.
1012
+ * @param {string} [referenceAttributeName] - The attribute name to use for the reference.
1013
+ */
1014
+ loadRefs(element, refs, referenceAttributeName) {
1000
1015
  for (const ref in refs) {
1001
1016
  const refType = refs[ref];
1002
1017
  const isString = typeof refType === 'string';
1003
- const selector = isString && refType.includes('scope') ? `:scope > [ref="${ref}"]` : `[ref="${ref}"]`;
1018
+ const selector = isString && refType.includes('scope')
1019
+ ? `:scope > [${referenceAttributeName || this._referenceAttributeName || 'ref'}="${ref}"]`
1020
+ : `[${referenceAttributeName || this._referenceAttributeName || 'ref'}="${ref}"]`;
1004
1021
  if (isString && refType.startsWith('single')) {
1005
1022
  this.refs[ref] = element.querySelector(selector);
1006
1023
  }
@@ -1076,7 +1093,7 @@ class Component extends Element_1.default {
1076
1093
  });
1077
1094
  }
1078
1095
  createComponentModal(element, modalShouldBeOpened, currentValue) {
1079
- return new ComponentModal_1.default(this, element, modalShouldBeOpened, currentValue);
1096
+ return new ComponentModal_1.default(this, element, modalShouldBeOpened, currentValue, this._referenceAttributeName);
1080
1097
  }
1081
1098
  attach(element) {
1082
1099
  if (!this.builderMode && !this.previewMode && this.component.modalEdit) {
@@ -10,7 +10,8 @@ class ComponentModal {
10
10
  const children = component.renderTemplate('component', data, topLevel);
11
11
  return component.renderTemplate('componentModal', Object.assign(Object.assign({}, data), { children }));
12
12
  }
13
- constructor(component, element, isOpened, currentValue) {
13
+ constructor(component, element, isOpened, currentValue, referenceAttributeName = 'ref') {
14
+ this._referenceAttributeName = referenceAttributeName;
14
15
  this.isOpened = isOpened;
15
16
  this.component = component;
16
17
  this.element = element;
@@ -146,10 +147,10 @@ class ComponentModal {
146
147
  showDialog() {
147
148
  this.dialogElement = this.component.ce('div');
148
149
  const dialogContent = `
149
- <h3 ref="dialogHeader">${this.component.t('Do you want to clear changes?')}</h3>
150
+ <h3 ${this._referenceAttributeName}="dialogHeader">${this.component.t('Do you want to clear changes?')}</h3>
150
151
  <div style="display:flex; justify-content: flex-end;">
151
- <button ref="dialogCancelButton" class="btn btn-secondary">${this.component.t('Cancel')}</button>
152
- <button ref="dialogYesButton" class="btn btn-danger">${this.component.t('Yes, delete it')}</button>
152
+ <button ${this._referenceAttributeName}="dialogCancelButton" class="btn btn-secondary">${this.component.t('Cancel')}</button>
153
+ <button ${this._referenceAttributeName}="dialogYesButton" class="btn btn-danger">${this.component.t('Yes, delete it')}</button>
153
154
  </div>
154
155
  `;
155
156
  this.dialogElement.innerHTML = dialogContent;
@@ -106,7 +106,7 @@ class Input extends Multivalue_1.default {
106
106
  }).trim();
107
107
  if (this.component.prefix !== calendarIcon) {
108
108
  // converting string to HTML markup to render correctly DateTime component in portal.form.io
109
- return (0, utils_1.convertStringToHTMLElement)(calendarIcon, '[ref="icon"]');
109
+ return (0, utils_1.convertStringToHTMLElement)(calendarIcon, `[${this._referenceAttributeName}="icon"]`);
110
110
  }
111
111
  }
112
112
  return this.component.suffix;
@@ -37,7 +37,7 @@ class Multivalue extends Field_1.default {
37
37
  render() {
38
38
  // If single value field.
39
39
  if (!this.useWrapper()) {
40
- return super.render(`<div ref="element">
40
+ return super.render(`<div ${this._referenceAttributeName}="element">
41
41
  ${this.renderElement(this.component.type !== 'hidden' ? this.dataValue : '')}
42
42
  </div>`);
43
43
  }
@@ -7,6 +7,7 @@ const lodash_1 = __importDefault(require("lodash"));
7
7
  const Field_1 = __importDefault(require("../field/Field"));
8
8
  const Components_1 = __importDefault(require("../../Components"));
9
9
  const utils_1 = require("../../../utils/utils");
10
+ const Component_1 = __importDefault(require("../component/Component"));
10
11
  const process_1 = require("@formio/core/process");
11
12
  class NestedComponent extends Field_1.default {
12
13
  static schema(...extend) {
@@ -188,8 +189,9 @@ class NestedComponent extends Field_1.default {
188
189
  * component tree.
189
190
  *
190
191
  * @param {string} key - The key of the component to retrieve.
191
- * @param {function} fn - Called with the component once found.
192
- * @return {Object} - The component that is located.
192
+ * @param {function} [fn] - Called with the component once found.
193
+ * @param {string} [originalPath] - The original path to the component.
194
+ * @return {Component} - The component that is located.
193
195
  */
194
196
  getComponent(path, fn, originalPath) {
195
197
  originalPath = originalPath || (0, utils_1.getStringFromComponentPath)(path);
@@ -263,7 +263,7 @@ class DataGridComponent extends NestedArrayComponent_1.default {
263
263
  loadRefs(element, refs) {
264
264
  super.loadRefs(element, refs);
265
265
  if (refs['messageContainer'] === 'single') {
266
- const container = lodash_1.default.last(element.querySelectorAll('[ref=messageContainer]'));
266
+ const container = lodash_1.default.last(element.querySelectorAll(`[${this._referenceAttributeName}=messageContainer]`));
267
267
  this.refs['messageContainer'] = container || this.refs['messageContainer'];
268
268
  }
269
269
  }
@@ -120,10 +120,10 @@ class EditGridComponent extends NestedArrayComponent_1.default {
120
120
  }
121
121
  get defaultDialogTemplate() {
122
122
  return `
123
- <h3 ref="dialogHeader">${this.t('Do you want to clear data?')}</h3>
123
+ <h3 ${this._referenceAttributeName}="dialogHeader">${this.t('Do you want to clear data?')}</h3>
124
124
  <div style="display:flex; justify-content: flex-end;">
125
- <button ref="dialogCancelButton" class="btn btn-secondary" aria-label="${this.t('Cancel')}">${this.t('Cancel')}</button>
126
- <button ref="dialogYesButton" class="btn btn-danger" aria-label="${this.t('Yes, delete it')}">${this.t('Yes, delete it')}</button>
125
+ <button ${this._referenceAttributeName}="dialogCancelButton" class="btn btn-secondary" aria-label="${this.t('Cancel')}">${this.t('Cancel')}</button>
126
+ <button ${this._referenceAttributeName}="dialogYesButton" class="btn btn-danger" aria-label="${this.t('Yes, delete it')}">${this.t('Yes, delete it')}</button>
127
127
  </div>
128
128
  `;
129
129
  }
@@ -293,7 +293,7 @@ class FormComponent extends Component_1.default {
293
293
  if (!this.builderMode && this.component.modalEdit) {
294
294
  const modalShouldBeOpened = this.componentModal ? this.componentModal.isOpened : false;
295
295
  const currentValue = modalShouldBeOpened ? this.componentModal.currentValue : this.dataValue;
296
- this.componentModal = new ComponentModal_1.default(this, element, modalShouldBeOpened, currentValue);
296
+ this.componentModal = new ComponentModal_1.default(this, element, modalShouldBeOpened, currentValue, this._referenceAttributeName);
297
297
  this.setOpenModalElement();
298
298
  }
299
299
  this.calculateValue();
@@ -43,13 +43,13 @@ class HTMLComponent extends Component_1.default {
43
43
  return ` ${this.component.content} `;
44
44
  }
45
45
  const submission = lodash_1.default.get(this.root, 'submission', {});
46
- const content = this.component.content ? this.interpolate(this.component.content, {
46
+ const content = this.component.content ? this.interpolate(this.sanitize(this.component.content, this.shouldSanitizeValue), {
47
47
  metadata: submission.metadata || {},
48
48
  submission: submission,
49
49
  data: this.rootValue,
50
50
  row: this.data
51
51
  }) : '';
52
- return this.sanitize(content, this.shouldSanitizeValue);
52
+ return content;
53
53
  }
54
54
  get singleTags() {
55
55
  return ['br', 'img', 'hr'];
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = {
4
+ type: 'form',
5
+ display: 'form',
6
+ components: [
7
+ {
8
+ label: 'Text Field',
9
+ applyMaskOn: 'change',
10
+ tableView: true,
11
+ key: 'textField',
12
+ type: 'textfield',
13
+ input: true,
14
+ },
15
+ {
16
+ label: 'HTML',
17
+ attrs: [
18
+ {
19
+ attr: '',
20
+ value: '',
21
+ },
22
+ ],
23
+ content: '<img src=1 onerror=alert("htmlContent")>\n<div class="myClass {{data.textField + \'-class\'}}">{{' +
24
+ ' data.textField ? data.textField : \'No Text\'}}</div>',
25
+ refreshOnChange: true,
26
+ key: 'html',
27
+ type: 'htmlelement',
28
+ input: false,
29
+ tableView: false,
30
+ },
31
+ {
32
+ type: 'button',
33
+ label: 'Submit',
34
+ key: 'submit',
35
+ disableOnInvalid: true,
36
+ input: true,
37
+ tableView: false,
38
+ },
39
+ ],
40
+ };
@@ -3,8 +3,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.comp2 = exports.comp1 = void 0;
6
+ exports.comp3 = exports.comp2 = exports.comp1 = void 0;
7
7
  const comp1_1 = __importDefault(require("./comp1"));
8
8
  exports.comp1 = comp1_1.default;
9
9
  const comp2_1 = __importDefault(require("./comp2"));
10
10
  exports.comp2 = comp2_1.default;
11
+ const comp3_1 = __importDefault(require("./comp3"));
12
+ exports.comp3 = comp3_1.default;
@@ -166,7 +166,8 @@ class RadioComponent extends ListComponent_1.default {
166
166
  dataValue = lodash_1.default.toString(this.dataValue);
167
167
  }
168
168
  if (this.isSelectURL && lodash_1.default.isObject(this.loadedOptions[index].value)) {
169
- input.checked = lodash_1.default.isEqual(this.loadedOptions[index].value, this.dataValue);
169
+ const optionValue = this.component.dataType === 'string' ? JSON.stringify(this.loadedOptions[index].value) : this.loadedOptions[index].value;
170
+ input.checked = lodash_1.default.isEqual(optionValue, this.dataValue);
170
171
  }
171
172
  else {
172
173
  input.checked = (dataValue === input.value && (input.value || this.component.dataSrc !== 'url'));
@@ -362,18 +363,36 @@ class RadioComponent extends ListComponent_1.default {
362
363
  * @return {*}
363
364
  */
364
365
  normalizeValue(value) {
366
+ const dataType = this.component.dataType || 'auto';
365
367
  if (value === this.emptyValue) {
366
368
  return value;
367
369
  }
368
- const isEquivalent = lodash_1.default.toString(value) === Number(value).toString();
369
- if (!isNaN(parseFloat(value)) && isFinite(value) && isEquivalent) {
370
- value = +value;
371
- }
372
- if (value === 'true') {
373
- value = true;
374
- }
375
- if (value === 'false') {
376
- value = false;
370
+ switch (dataType) {
371
+ case 'auto':
372
+ if (!isNaN(parseFloat(value)) && isFinite(value) && lodash_1.default.toString(value) === Number(value).toString()) {
373
+ value = +value;
374
+ }
375
+ if (value === 'true') {
376
+ value = true;
377
+ }
378
+ if (value === 'false') {
379
+ value = false;
380
+ }
381
+ break;
382
+ case 'number':
383
+ value = +value;
384
+ break;
385
+ case 'string':
386
+ if (typeof value === 'object') {
387
+ value = JSON.stringify(value);
388
+ }
389
+ else {
390
+ value = String(value);
391
+ }
392
+ break;
393
+ case 'boolean':
394
+ value = !(!value || value.toString() === 'false');
395
+ break;
377
396
  }
378
397
  if (this.isSelectURL && this.templateData && this.templateData[value]) {
379
398
  const submission = this.root.submission;
@@ -76,6 +76,26 @@ exports.default = [
76
76
  json: { '===': [{ var: 'data.dataSrc' }, 'values'] },
77
77
  },
78
78
  },
79
+ {
80
+ type: 'select',
81
+ input: true,
82
+ label: 'Storage Type',
83
+ key: 'dataType',
84
+ clearOnHide: true,
85
+ tooltip: 'The type to store the data. If you select something other than autotype, it will force it to that type.',
86
+ weight: 12,
87
+ template: '<span>{{ item.label }}</span>',
88
+ dataSrc: 'values',
89
+ data: {
90
+ values: [
91
+ { label: 'Autotype', value: 'auto' },
92
+ { label: 'String', value: 'string' },
93
+ { label: 'Number', value: 'number' },
94
+ { label: 'Boolean', value: 'boolean' },
95
+ { label: 'Object', value: 'object' },
96
+ ],
97
+ },
98
+ },
79
99
  {
80
100
  key: 'template',
81
101
  conditional: {