@formio/js 5.1.0-dev.5969.9a6e3f5 → 5.1.0-dev.5972.317ce89
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.
- package/dist/formio.form.js +74 -52
- package/dist/formio.form.min.js +1 -1
- package/dist/formio.full.js +77 -55
- package/dist/formio.full.min.js +1 -1
- package/dist/formio.js +3 -3
- package/dist/formio.min.js +1 -1
- package/dist/formio.utils.js +3 -3
- package/dist/formio.utils.min.js +1 -1
- package/lib/cjs/Form.js +4 -4
- package/lib/cjs/PDFBuilder.js +4 -4
- package/lib/cjs/Webform.d.ts +12 -12
- package/lib/cjs/Webform.js +132 -131
- package/lib/cjs/WebformBuilder.js +10 -10
- package/lib/cjs/Wizard.js +1 -1
- package/lib/cjs/WizardBuilder.js +1 -1
- package/lib/cjs/components/_classes/component/Component.js +12 -11
- package/lib/cjs/components/_classes/list/ListComponent.js +4 -4
- package/lib/cjs/components/_classes/multivalue/Multivalue.js +2 -2
- package/lib/cjs/components/_classes/nestedarray/NestedArrayComponent.js +3 -3
- package/lib/cjs/components/address/Address.js +1 -1
- package/lib/cjs/components/button/Button.js +6 -6
- package/lib/cjs/components/checkbox/Checkbox.js +1 -1
- package/lib/cjs/components/datagrid/DataGrid.js +1 -1
- package/lib/cjs/components/datetime/DateTime.js +4 -0
- package/lib/cjs/components/day/Day.js +4 -20
- package/lib/cjs/components/editgrid/EditGrid.js +4 -4
- package/lib/cjs/components/file/File.js +15 -15
- package/lib/cjs/components/form/Form.js +4 -4
- package/lib/cjs/components/number/Number.js +1 -1
- package/lib/cjs/components/recaptcha/ReCaptcha.js +2 -2
- package/lib/cjs/components/select/Select.js +5 -5
- package/lib/cjs/components/selectboxes/SelectBoxes.js +2 -2
- package/lib/cjs/components/signature/Signature.d.ts +1 -1
- package/lib/cjs/components/signature/Signature.js +2 -2
- package/lib/cjs/components/survey/Survey.js +2 -2
- package/lib/cjs/components/textarea/TextArea.js +6 -6
- package/lib/cjs/components/textfield/TextField.js +3 -0
- package/lib/cjs/formio.form.js +4 -0
- package/lib/cjs/translations/en.d.ts +234 -81
- package/lib/cjs/translations/en.js +8 -81
- package/lib/cjs/utils/i18n.d.ts +5 -2
- package/lib/cjs/utils/i18n.js +32 -5
- package/lib/mjs/Form.js +4 -4
- package/lib/mjs/PDFBuilder.js +4 -4
- package/lib/mjs/Webform.d.ts +12 -12
- package/lib/mjs/Webform.js +142 -141
- package/lib/mjs/WebformBuilder.js +10 -10
- package/lib/mjs/Wizard.js +1 -1
- package/lib/mjs/WizardBuilder.js +1 -1
- package/lib/mjs/components/_classes/component/Component.js +12 -11
- package/lib/mjs/components/_classes/list/ListComponent.js +4 -4
- package/lib/mjs/components/_classes/multivalue/Multivalue.js +2 -2
- package/lib/mjs/components/_classes/nestedarray/NestedArrayComponent.js +3 -3
- package/lib/mjs/components/address/Address.js +1 -1
- package/lib/mjs/components/button/Button.js +6 -6
- package/lib/mjs/components/checkbox/Checkbox.js +1 -1
- package/lib/mjs/components/datagrid/DataGrid.js +1 -1
- package/lib/mjs/components/datetime/DateTime.js +5 -1
- package/lib/mjs/components/day/Day.js +4 -20
- package/lib/mjs/components/editgrid/EditGrid.js +4 -4
- package/lib/mjs/components/file/File.js +15 -15
- package/lib/mjs/components/form/Form.js +4 -4
- package/lib/mjs/components/number/Number.js +1 -1
- package/lib/mjs/components/recaptcha/ReCaptcha.js +2 -2
- package/lib/mjs/components/select/Select.js +7 -7
- package/lib/mjs/components/selectboxes/SelectBoxes.js +2 -2
- package/lib/mjs/components/signature/Signature.d.ts +1 -1
- package/lib/mjs/components/signature/Signature.js +2 -2
- package/lib/mjs/components/survey/Survey.js +2 -2
- package/lib/mjs/components/textarea/TextArea.js +6 -6
- package/lib/mjs/components/textfield/TextField.js +3 -0
- package/lib/mjs/formio.form.js +4 -0
- package/lib/mjs/translations/en.d.ts +234 -81
- package/lib/mjs/translations/en.js +89 -3
- package/lib/mjs/utils/i18n.d.ts +5 -2
- package/lib/mjs/utils/i18n.js +32 -5
- package/package.json +3 -3
package/lib/mjs/Webform.js
CHANGED
@@ -1,13 +1,13 @@
|
|
1
|
-
import _ from
|
2
|
-
import moment from
|
3
|
-
import { compareVersions } from
|
4
|
-
import EventEmitter from
|
5
|
-
import i18nDefaults from
|
6
|
-
import { Formio } from
|
7
|
-
import Components from
|
8
|
-
import NestedDataComponent from
|
9
|
-
import { fastCloneDeep, currentTimezone, unescapeHTML, getStringFromComponentPath, convertStringToHTMLElement, getArrayFromComponentPath, } from
|
10
|
-
import { eachComponent } from
|
1
|
+
import _ from 'lodash';
|
2
|
+
import moment from 'moment';
|
3
|
+
import { compareVersions } from 'compare-versions';
|
4
|
+
import EventEmitter from './EventEmitter';
|
5
|
+
import i18nDefaults from './i18n';
|
6
|
+
import { Formio } from './Formio';
|
7
|
+
import Components from './components/Components';
|
8
|
+
import NestedDataComponent from './components/_classes/nesteddata/NestedDataComponent';
|
9
|
+
import { fastCloneDeep, currentTimezone, unescapeHTML, getStringFromComponentPath, convertStringToHTMLElement, getArrayFromComponentPath, } from './utils/utils';
|
10
|
+
import { eachComponent } from './utils/formUtils';
|
11
11
|
// We need this here because dragula pulls in CustomEvent class that requires global to exist.
|
12
12
|
if (typeof window !== 'undefined' && typeof window.global === 'undefined') {
|
13
13
|
window.global = window;
|
@@ -22,10 +22,10 @@ Formio.registerComponent = Components.setComponent;
|
|
22
22
|
* @returns {any} - The icon set.
|
23
23
|
*/
|
24
24
|
function getIconSet(icons) {
|
25
|
-
if (icons ===
|
26
|
-
return
|
25
|
+
if (icons === 'fontawesome') {
|
26
|
+
return 'fa';
|
27
27
|
}
|
28
|
-
return icons ||
|
28
|
+
return icons || '';
|
29
29
|
}
|
30
30
|
/**
|
31
31
|
*
|
@@ -40,7 +40,7 @@ function getOptions(options) {
|
|
40
40
|
saveDraft: false,
|
41
41
|
alwaysDirty: false,
|
42
42
|
saveDraftThrottle: 5000,
|
43
|
-
display:
|
43
|
+
display: 'form',
|
44
44
|
cdnUrl: Formio.cdn.baseUrl,
|
45
45
|
});
|
46
46
|
if (!options.events) {
|
@@ -84,10 +84,10 @@ function getOptions(options) {
|
|
84
84
|
*/
|
85
85
|
/**
|
86
86
|
* @typedef {object} ButtonSettings
|
87
|
-
* @property {boolean} [showPrevious] - Show the
|
88
|
-
* @property {boolean} [showNext] - Show the
|
89
|
-
* @property {boolean} [showCancel] - Show the
|
90
|
-
* @property {boolean} [showSubmit] - Show the
|
87
|
+
* @property {boolean} [showPrevious] - Show the 'Previous' button.
|
88
|
+
* @property {boolean} [showNext] - Show the 'Next' button.
|
89
|
+
* @property {boolean} [showCancel] - Show the 'Cancel' button.
|
90
|
+
* @property {boolean} [showSubmit] - Show the 'Submit' button.
|
91
91
|
*/
|
92
92
|
/**
|
93
93
|
* @typedef {object} FormOptions
|
@@ -164,8 +164,8 @@ export default class Webform extends NestedDataComponent {
|
|
164
164
|
* The type of this element.
|
165
165
|
* @type {string}
|
166
166
|
*/
|
167
|
-
this.type =
|
168
|
-
this._src =
|
167
|
+
this.type = 'form';
|
168
|
+
this._src = '';
|
169
169
|
this._loading = false;
|
170
170
|
this._form = {};
|
171
171
|
this.draftEnabled = false;
|
@@ -313,7 +313,7 @@ export default class Webform extends NestedDataComponent {
|
|
313
313
|
return;
|
314
314
|
}
|
315
315
|
this.rebuild();
|
316
|
-
this.emit(
|
316
|
+
this.emit('languageChanged');
|
317
317
|
});
|
318
318
|
}
|
319
319
|
get componentComponents() {
|
@@ -331,18 +331,18 @@ export default class Webform extends NestedDataComponent {
|
|
331
331
|
addLanguage(code, lang, active = false) {
|
332
332
|
if (this.i18next) {
|
333
333
|
var translations = _.assign(fastCloneDeep(i18nDefaults.resources.en.translation), lang);
|
334
|
-
this.i18next.addResourceBundle(code,
|
334
|
+
this.i18next.addResourceBundle(code, 'translation', translations, true, true);
|
335
335
|
if (active) {
|
336
336
|
this.language = code;
|
337
337
|
}
|
338
338
|
}
|
339
339
|
}
|
340
340
|
keyboardCatchableElement(element) {
|
341
|
-
if (element.nodeName ===
|
341
|
+
if (element.nodeName === 'TEXTAREA') {
|
342
342
|
return false;
|
343
343
|
}
|
344
|
-
if (element.nodeName ===
|
345
|
-
return [
|
344
|
+
if (element.nodeName === 'INPUT') {
|
345
|
+
return ['text', 'email', 'password'].indexOf(element.type) === -1;
|
346
346
|
}
|
347
347
|
return true;
|
348
348
|
}
|
@@ -353,15 +353,15 @@ export default class Webform extends NestedDataComponent {
|
|
353
353
|
}
|
354
354
|
const ctrl = event.ctrlKey || event.metaKey;
|
355
355
|
const keyCode = event.keyCode;
|
356
|
-
let char =
|
356
|
+
let char = '';
|
357
357
|
if (65 <= keyCode && keyCode <= 90) {
|
358
358
|
char = String.fromCharCode(keyCode);
|
359
359
|
}
|
360
360
|
else if (keyCode === 13) {
|
361
|
-
char =
|
361
|
+
char = 'Enter';
|
362
362
|
}
|
363
363
|
else if (keyCode === 27) {
|
364
|
-
char =
|
364
|
+
char = 'Esc';
|
365
365
|
}
|
366
366
|
_.each(this.shortcuts, (shortcut) => {
|
367
367
|
if (shortcut.ctrl && !ctrl) {
|
@@ -378,9 +378,9 @@ export default class Webform extends NestedDataComponent {
|
|
378
378
|
return;
|
379
379
|
}
|
380
380
|
shortcut = _.capitalize(shortcut);
|
381
|
-
if (shortcut ===
|
381
|
+
if (shortcut === 'Enter' || shortcut === 'Esc') {
|
382
382
|
// Restrict Enter and Esc only for buttons
|
383
|
-
if (element.tagName !==
|
383
|
+
if (element.tagName !== 'BUTTON') {
|
384
384
|
return;
|
385
385
|
}
|
386
386
|
this.shortcuts.push({
|
@@ -480,13 +480,13 @@ export default class Webform extends NestedDataComponent {
|
|
480
480
|
* @returns {boolean} - TRUE means the url was set, FALSE otherwise.
|
481
481
|
*/
|
482
482
|
setUrl(value, options) {
|
483
|
-
if (!value || typeof value !==
|
483
|
+
if (!value || typeof value !== 'string' || value === this._src) {
|
484
484
|
return false;
|
485
485
|
}
|
486
486
|
this._src = value;
|
487
487
|
this.nosubmit = true;
|
488
488
|
this.formio = this.options.formio = new Formio(value, options);
|
489
|
-
if (this.type ===
|
489
|
+
if (this.type === 'form') {
|
490
490
|
// Set the options source so this can be passed to other components.
|
491
491
|
this.options.src = value;
|
492
492
|
}
|
@@ -519,17 +519,17 @@ export default class Webform extends NestedDataComponent {
|
|
519
519
|
}
|
520
520
|
/**
|
521
521
|
* Set the loading state for this form, and also show the loader spinner.
|
522
|
-
* @param {boolean} loading - If this form should be
|
522
|
+
* @param {boolean} loading - If this form should be 'loading' or not.
|
523
523
|
*/
|
524
524
|
set loading(loading) {
|
525
525
|
if (this._loading !== loading) {
|
526
526
|
this._loading = loading;
|
527
527
|
if (!this.loader && loading) {
|
528
|
-
this.loader = this.ce(
|
529
|
-
class:
|
528
|
+
this.loader = this.ce('div', {
|
529
|
+
class: 'loader-wrapper',
|
530
530
|
});
|
531
|
-
const spinner = this.ce(
|
532
|
-
class:
|
531
|
+
const spinner = this.ce('div', {
|
532
|
+
class: 'loader text-center',
|
533
533
|
});
|
534
534
|
this.loader.appendChild(spinner);
|
535
535
|
}
|
@@ -613,18 +613,18 @@ export default class Webform extends NestedDataComponent {
|
|
613
613
|
// Use the sanitize config from the form settings or the global sanitize config if it is not provided in the options
|
614
614
|
if (!this.options.sanitizeConfig && !this.builderMode) {
|
615
615
|
this.options.sanitizeConfig =
|
616
|
-
_.get(form,
|
617
|
-
_.get(form,
|
616
|
+
_.get(form, 'settings.sanitizeConfig') ||
|
617
|
+
_.get(form, 'globalSettings.sanitizeConfig');
|
618
618
|
}
|
619
|
-
if (
|
619
|
+
if ('schema' in form && compareVersions(form.schema, '1.x') > 0) {
|
620
620
|
this.ready.then(() => {
|
621
|
-
this.setAlert(
|
621
|
+
this.setAlert('alert alert-danger', this.t('newFormSchema'));
|
622
622
|
});
|
623
623
|
}
|
624
624
|
// See if they pass a module, and evaluate it if so.
|
625
625
|
if (form && form.module) {
|
626
626
|
let formModule = null;
|
627
|
-
if (typeof form.module ===
|
627
|
+
if (typeof form.module === 'string') {
|
628
628
|
try {
|
629
629
|
formModule = this.evaluate(`return ${form.module}`);
|
630
630
|
}
|
@@ -646,7 +646,7 @@ export default class Webform extends NestedDataComponent {
|
|
646
646
|
this.initialized = false;
|
647
647
|
const rebuild = this.rebuild() || Promise.resolve();
|
648
648
|
return rebuild.then(() => {
|
649
|
-
this.emit(
|
649
|
+
this.emit('formLoad', form);
|
650
650
|
this.triggerCaptcha();
|
651
651
|
// Make sure to trigger onChange after a render event occurs to speed up form rendering.
|
652
652
|
setTimeout(() => {
|
@@ -720,7 +720,7 @@ export default class Webform extends NestedDataComponent {
|
|
720
720
|
setSubmission(submission, flags = {}) {
|
721
721
|
flags = {
|
722
722
|
...flags,
|
723
|
-
fromSubmission: _.has(flags,
|
723
|
+
fromSubmission: _.has(flags, 'fromSubmission') ? flags.fromSubmission : true,
|
724
724
|
};
|
725
725
|
return (this.onSubmission = this.formReady
|
726
726
|
.then((resolveFlags) => {
|
@@ -736,26 +736,26 @@ export default class Webform extends NestedDataComponent {
|
|
736
736
|
.catch((err) => this.submissionReadyReject(err)));
|
737
737
|
}
|
738
738
|
handleDraftError(errName, errDetails, restoreDraft) {
|
739
|
-
const errorMessage = _.trim(`${this.t(errName)} ${errDetails ||
|
739
|
+
const errorMessage = _.trim(`${this.t(errName)} ${errDetails || ''}`);
|
740
740
|
console.warn(errorMessage);
|
741
|
-
this.emit(restoreDraft ?
|
741
|
+
this.emit(restoreDraft ? 'restoreDraftError' : 'saveDraftError', errDetails || errorMessage);
|
742
742
|
}
|
743
743
|
saveDraft() {
|
744
744
|
if (!this.draftEnabled || this.parent?.component.reference === false) {
|
745
745
|
return;
|
746
746
|
}
|
747
747
|
if (!this.formio) {
|
748
|
-
this.handleDraftError(
|
748
|
+
this.handleDraftError('saveDraftInstanceError');
|
749
749
|
return;
|
750
750
|
}
|
751
751
|
if (!Formio.getUser()) {
|
752
|
-
this.handleDraftError(
|
752
|
+
this.handleDraftError('saveDraftAuthError');
|
753
753
|
return;
|
754
754
|
}
|
755
755
|
const draft = fastCloneDeep(this.submission);
|
756
|
-
draft.state =
|
756
|
+
draft.state = 'draft';
|
757
757
|
if (!this.savingDraft && !this.submitting) {
|
758
|
-
this.emit(
|
758
|
+
this.emit('saveDraftBegin');
|
759
759
|
this.savingDraft = true;
|
760
760
|
this.formio
|
761
761
|
.saveSubmission(draft)
|
@@ -763,11 +763,11 @@ export default class Webform extends NestedDataComponent {
|
|
763
763
|
// Set id to submission to avoid creating new draft submission
|
764
764
|
this.submission._id = sub._id;
|
765
765
|
this.savingDraft = false;
|
766
|
-
this.emit(
|
766
|
+
this.emit('saveDraft', sub);
|
767
767
|
})
|
768
768
|
.catch((err) => {
|
769
769
|
this.savingDraft = false;
|
770
|
-
this.handleDraftError(
|
770
|
+
this.handleDraftError('saveDraftError', err);
|
771
771
|
});
|
772
772
|
}
|
773
773
|
}
|
@@ -778,7 +778,7 @@ export default class Webform extends NestedDataComponent {
|
|
778
778
|
restoreDraft(userId) {
|
779
779
|
const formio = this.formio || this.options.formio;
|
780
780
|
if (!formio) {
|
781
|
-
this.handleDraftError(
|
781
|
+
this.handleDraftError('restoreDraftInstanceError', null, true);
|
782
782
|
return;
|
783
783
|
}
|
784
784
|
this.savingDraft = true;
|
@@ -796,22 +796,22 @@ export default class Webform extends NestedDataComponent {
|
|
796
796
|
return this.setSubmission(draft).then(() => {
|
797
797
|
this.draftEnabled = true;
|
798
798
|
this.savingDraft = false;
|
799
|
-
this.emit(
|
799
|
+
this.emit('restoreDraft', draft);
|
800
800
|
});
|
801
801
|
}
|
802
802
|
// Enable drafts so that we can keep track of changes.
|
803
803
|
this.draftEnabled = true;
|
804
804
|
this.savingDraft = false;
|
805
|
-
this.emit(
|
805
|
+
this.emit('restoreDraft', null);
|
806
806
|
})
|
807
807
|
.catch((err) => {
|
808
808
|
this.draftEnabled = true;
|
809
809
|
this.savingDraft = false;
|
810
|
-
this.handleDraftError(
|
810
|
+
this.handleDraftError('restoreDraftError', err, true);
|
811
811
|
});
|
812
812
|
}
|
813
813
|
get schema() {
|
814
|
-
const schema = fastCloneDeep(_.omit(this._form, [
|
814
|
+
const schema = fastCloneDeep(_.omit(this._form, ['components']));
|
815
815
|
schema.components = [];
|
816
816
|
this.eachComponent((component) => schema.components.push(component.schema));
|
817
817
|
return schema;
|
@@ -886,10 +886,10 @@ export default class Webform extends NestedDataComponent {
|
|
886
886
|
else {
|
887
887
|
this.component = this.form;
|
888
888
|
}
|
889
|
-
this.component.type =
|
889
|
+
this.component.type = 'form';
|
890
890
|
this.component.input = false;
|
891
891
|
this.addComponents();
|
892
|
-
this.on(
|
892
|
+
this.on('submitButton', (options) => {
|
893
893
|
this.submit(false, options).catch((e) => {
|
894
894
|
if (options?.instance) {
|
895
895
|
options.instance.loading = false;
|
@@ -897,11 +897,11 @@ export default class Webform extends NestedDataComponent {
|
|
897
897
|
return e !== false && e !== undefined && console.log(e);
|
898
898
|
});
|
899
899
|
}, true);
|
900
|
-
this.on(
|
901
|
-
this.on(
|
902
|
-
this.on(
|
903
|
-
this.on(
|
904
|
-
this.on(
|
900
|
+
this.on('checkValidity', (data) => this.validate(data, { dirty: true, process: 'change' }), true);
|
901
|
+
this.on('requestUrl', (args) => this.submitUrl(args.url, args.headers), true);
|
902
|
+
this.on('resetForm', () => this.resetValue(), true);
|
903
|
+
this.on('deleteSubmission', () => this.deleteSubmission(), true);
|
904
|
+
this.on('refreshData', () => this.updateValue(), true);
|
905
905
|
this.executeFormController();
|
906
906
|
return this.formReady;
|
907
907
|
}
|
@@ -926,19 +926,19 @@ export default class Webform extends NestedDataComponent {
|
|
926
926
|
*
|
927
927
|
*/
|
928
928
|
teardown() {
|
929
|
-
this.emit(
|
929
|
+
this.emit('formDelete', this.id);
|
930
930
|
delete Formio.forms[this.id];
|
931
931
|
delete this.executeShortcuts;
|
932
932
|
delete this.triggerSaveDraft;
|
933
933
|
super.teardown();
|
934
934
|
}
|
935
935
|
destroy(all = false) {
|
936
|
-
this.off(
|
937
|
-
this.off(
|
938
|
-
this.off(
|
939
|
-
this.off(
|
940
|
-
this.off(
|
941
|
-
this.off(
|
936
|
+
this.off('submitButton');
|
937
|
+
this.off('checkValidity');
|
938
|
+
this.off('requestUrl');
|
939
|
+
this.off('resetForm');
|
940
|
+
this.off('deleteSubmission');
|
941
|
+
this.off('refreshData');
|
942
942
|
return super.destroy(all);
|
943
943
|
}
|
944
944
|
build(element) {
|
@@ -951,17 +951,17 @@ export default class Webform extends NestedDataComponent {
|
|
951
951
|
return this.ready;
|
952
952
|
}
|
953
953
|
getClassName() {
|
954
|
-
let classes =
|
954
|
+
let classes = 'formio-form';
|
955
955
|
if (this.options.readOnly) {
|
956
|
-
classes +=
|
956
|
+
classes += ' formio-read-only';
|
957
957
|
}
|
958
958
|
return classes;
|
959
959
|
}
|
960
960
|
render() {
|
961
|
-
return super.render(this.renderTemplate(
|
961
|
+
return super.render(this.renderTemplate('webform', {
|
962
962
|
classes: this.getClassName(),
|
963
963
|
children: this.renderComponents(),
|
964
|
-
}), this.builderMode ?
|
964
|
+
}), this.builderMode ? 'builder' : 'form', true);
|
965
965
|
}
|
966
966
|
redraw() {
|
967
967
|
// Don't bother if we have not built yet.
|
@@ -974,13 +974,13 @@ export default class Webform extends NestedDataComponent {
|
|
974
974
|
}
|
975
975
|
attach(element) {
|
976
976
|
this.setElement(element);
|
977
|
-
this.loadRefs(element, { webform:
|
977
|
+
this.loadRefs(element, { webform: 'single' });
|
978
978
|
const childPromise = this.attachComponents(this.refs.webform);
|
979
|
-
this.addEventListener(document,
|
979
|
+
this.addEventListener(document, 'keydown', this.executeShortcuts);
|
980
980
|
this.currentForm = this;
|
981
|
-
this.hook(
|
981
|
+
this.hook('attachWebform', element, this);
|
982
982
|
return childPromise.then(() => {
|
983
|
-
this.emit(
|
983
|
+
this.emit('render', this.element);
|
984
984
|
return this.setValue(this._submission, {
|
985
985
|
noUpdateEvent: true,
|
986
986
|
});
|
@@ -1003,7 +1003,7 @@ export default class Webform extends NestedDataComponent {
|
|
1003
1003
|
}
|
1004
1004
|
/**
|
1005
1005
|
* Sets a new alert to display in the error dialog of the form.
|
1006
|
-
* @param {string} type - The type of alert to display.
|
1006
|
+
* @param {string} type - The type of alert to display. 'danger', 'success', 'warning', etc.
|
1007
1007
|
* @param {string} message - The message to show in the alert.
|
1008
1008
|
* @param {object} options - The options for the alert.
|
1009
1009
|
*/
|
@@ -1012,8 +1012,8 @@ export default class Webform extends NestedDataComponent {
|
|
1012
1012
|
if (this.alert) {
|
1013
1013
|
if (this.refs.errorRef && this.refs.errorRef.length) {
|
1014
1014
|
this.refs.errorRef.forEach((el) => {
|
1015
|
-
this.removeEventListener(el,
|
1016
|
-
this.removeEventListener(el,
|
1015
|
+
this.removeEventListener(el, 'click');
|
1016
|
+
this.removeEventListener(el, 'keypress');
|
1017
1017
|
});
|
1018
1018
|
}
|
1019
1019
|
this.removeChild(this.alert);
|
@@ -1023,7 +1023,7 @@ export default class Webform extends NestedDataComponent {
|
|
1023
1023
|
}
|
1024
1024
|
if (this.options.noAlerts) {
|
1025
1025
|
if (!message) {
|
1026
|
-
this.emit(
|
1026
|
+
this.emit('error', false);
|
1027
1027
|
}
|
1028
1028
|
return;
|
1029
1029
|
}
|
@@ -1031,8 +1031,8 @@ export default class Webform extends NestedDataComponent {
|
|
1031
1031
|
try {
|
1032
1032
|
if (this.refs.errorRef && this.refs.errorRef.length) {
|
1033
1033
|
this.refs.errorRef.forEach((el) => {
|
1034
|
-
this.removeEventListener(el,
|
1035
|
-
this.removeEventListener(el,
|
1034
|
+
this.removeEventListener(el, 'click');
|
1035
|
+
this.removeEventListener(el, 'keypress');
|
1036
1036
|
});
|
1037
1037
|
}
|
1038
1038
|
this.removeChild(this.alert);
|
@@ -1052,19 +1052,19 @@ export default class Webform extends NestedDataComponent {
|
|
1052
1052
|
attrs: attrs,
|
1053
1053
|
type,
|
1054
1054
|
};
|
1055
|
-
this.alert = convertStringToHTMLElement(this.renderTemplate(
|
1055
|
+
this.alert = convertStringToHTMLElement(this.renderTemplate('alert', templateOptions), `#${attrs.id}`);
|
1056
1056
|
}
|
1057
1057
|
if (!this.alert) {
|
1058
1058
|
return;
|
1059
1059
|
}
|
1060
|
-
this.loadRefs(this.alert, { errorRef:
|
1060
|
+
this.loadRefs(this.alert, { errorRef: 'multiple' });
|
1061
1061
|
if (this.refs.errorRef && this.refs.errorRef.length) {
|
1062
1062
|
this.refs.errorRef.forEach((el) => {
|
1063
|
-
this.addEventListener(el,
|
1063
|
+
this.addEventListener(el, 'click', (e) => {
|
1064
1064
|
const key = e.currentTarget.dataset.componentKey;
|
1065
1065
|
this.focusOnComponent(key);
|
1066
1066
|
});
|
1067
|
-
this.addEventListener(el,
|
1067
|
+
this.addEventListener(el, 'keydown', (e) => {
|
1068
1068
|
if (e.keyCode === 13) {
|
1069
1069
|
e.preventDefault();
|
1070
1070
|
const key = e.currentTarget.dataset.componentKey;
|
@@ -1142,8 +1142,8 @@ export default class Webform extends NestedDataComponent {
|
|
1142
1142
|
(err.context?.component && err.context?.component.key) ||
|
1143
1143
|
(err.component && err.component.key) ||
|
1144
1144
|
(err.fromServer && err.path);
|
1145
|
-
const formattedKeyOrPath = keyOrPath ? getStringFromComponentPath(keyOrPath) :
|
1146
|
-
if (typeof err !==
|
1145
|
+
const formattedKeyOrPath = keyOrPath ? getStringFromComponentPath(keyOrPath) : '';
|
1146
|
+
if (typeof err !== 'string' && !err.formattedKeyOrPath) {
|
1147
1147
|
err.formattedKeyOrPath = formattedKeyOrPath;
|
1148
1148
|
}
|
1149
1149
|
return {
|
@@ -1153,18 +1153,18 @@ export default class Webform extends NestedDataComponent {
|
|
1153
1153
|
};
|
1154
1154
|
errors.forEach(({ message, context, fromServer, component }, index) => {
|
1155
1155
|
const text = !component?.label || context?.hasLabel || fromServer
|
1156
|
-
? this.t(
|
1157
|
-
: this.t(
|
1156
|
+
? this.t('alertMessage', { message: this.t(message) })
|
1157
|
+
: this.t('alertMessageWithLabel', {
|
1158
1158
|
label: this.t(component?.label),
|
1159
1159
|
message: this.t(message),
|
1160
1160
|
});
|
1161
1161
|
displayedErrors.push(createListItem(text, index));
|
1162
1162
|
});
|
1163
1163
|
}
|
1164
|
-
const errorsList = this.renderTemplate(
|
1165
|
-
this.root.setAlert(
|
1164
|
+
const errorsList = this.renderTemplate('errorsList', { errors: displayedErrors });
|
1165
|
+
this.root.setAlert('danger', errorsList);
|
1166
1166
|
if (triggerEvent) {
|
1167
|
-
this.emit(
|
1167
|
+
this.emit('error', errors);
|
1168
1168
|
}
|
1169
1169
|
return errors;
|
1170
1170
|
}
|
@@ -1184,23 +1184,23 @@ export default class Webform extends NestedDataComponent {
|
|
1184
1184
|
noValidate: true,
|
1185
1185
|
noCheck: true,
|
1186
1186
|
});
|
1187
|
-
this.setAlert(
|
1187
|
+
this.setAlert('success', `<p>${this.t('complete')}</p>`);
|
1188
1188
|
// Cancel triggered saveDraft to prevent overriding the submitted state
|
1189
1189
|
if (this.draftEnabled && this.triggerSaveDraft?.cancel) {
|
1190
1190
|
this.triggerSaveDraft.cancel();
|
1191
1191
|
}
|
1192
|
-
this.emit(
|
1192
|
+
this.emit('submit', submission, saved);
|
1193
1193
|
if (saved) {
|
1194
|
-
this.emit(
|
1194
|
+
this.emit('submitDone', submission);
|
1195
1195
|
}
|
1196
1196
|
return submission;
|
1197
1197
|
}
|
1198
1198
|
normalizeError(error) {
|
1199
1199
|
if (error) {
|
1200
|
-
if (typeof error ===
|
1200
|
+
if (typeof error === 'object' && 'details' in error) {
|
1201
1201
|
error = error.details;
|
1202
1202
|
}
|
1203
|
-
if (typeof error ===
|
1203
|
+
if (typeof error === 'string') {
|
1204
1204
|
error = { message: error };
|
1205
1205
|
}
|
1206
1206
|
}
|
@@ -1215,10 +1215,10 @@ export default class Webform extends NestedDataComponent {
|
|
1215
1215
|
error = this.normalizeError(error);
|
1216
1216
|
this.submitting = false;
|
1217
1217
|
this.setPristine(false);
|
1218
|
-
this.emit(
|
1218
|
+
this.emit('submitError', error || this.errors);
|
1219
1219
|
// Allow for silent cancellations (no error message, no submit button error state)
|
1220
1220
|
if (error && error.silent) {
|
1221
|
-
this.emit(
|
1221
|
+
this.emit('change', { isValid: true }, { silent: true });
|
1222
1222
|
return false;
|
1223
1223
|
}
|
1224
1224
|
const errors = this.showErrors(error, true);
|
@@ -1272,12 +1272,12 @@ export default class Webform extends NestedDataComponent {
|
|
1272
1272
|
this.triggerSaveDraft();
|
1273
1273
|
}
|
1274
1274
|
if (!flags || !flags.noEmit) {
|
1275
|
-
this.emit(
|
1275
|
+
this.emit('change', value, flags, modified);
|
1276
1276
|
isChangeEventEmitted = true;
|
1277
1277
|
}
|
1278
1278
|
// The form is initialized after the first change event occurs.
|
1279
1279
|
if (isChangeEventEmitted && !this.initialized) {
|
1280
|
-
this.emit(
|
1280
|
+
this.emit('initialized');
|
1281
1281
|
this.initialized = true;
|
1282
1282
|
}
|
1283
1283
|
}
|
@@ -1287,7 +1287,7 @@ export default class Webform extends NestedDataComponent {
|
|
1287
1287
|
*/
|
1288
1288
|
deleteSubmission() {
|
1289
1289
|
return this.formio.deleteSubmission().then(() => {
|
1290
|
-
this.emit(
|
1290
|
+
this.emit('submissionDeleted', this.submission);
|
1291
1291
|
this.resetValue();
|
1292
1292
|
});
|
1293
1293
|
}
|
@@ -1298,13 +1298,13 @@ export default class Webform extends NestedDataComponent {
|
|
1298
1298
|
* @returns {boolean} - TRUE means the submission was cancelled, FALSE otherwise.
|
1299
1299
|
*/
|
1300
1300
|
cancel(noconfirm) {
|
1301
|
-
const shouldReset = this.hook(
|
1302
|
-
if (shouldReset && (noconfirm || confirm(this.t(
|
1301
|
+
const shouldReset = this.hook('beforeCancel', true);
|
1302
|
+
if (shouldReset && (noconfirm || confirm(this.t('confirmCancel')))) {
|
1303
1303
|
this.resetValue();
|
1304
1304
|
return true;
|
1305
1305
|
}
|
1306
1306
|
else {
|
1307
|
-
this.emit(
|
1307
|
+
this.emit('cancelSubmit');
|
1308
1308
|
return false;
|
1309
1309
|
}
|
1310
1310
|
}
|
@@ -1312,8 +1312,8 @@ export default class Webform extends NestedDataComponent {
|
|
1312
1312
|
// Add in metadata about client submitting the form
|
1313
1313
|
submission.metadata = submission.metadata || {};
|
1314
1314
|
_.defaults(submission.metadata, {
|
1315
|
-
timezone: _.get(this,
|
1316
|
-
offset: parseInt(_.get(this,
|
1315
|
+
timezone: _.get(this, '_submission.metadata.timezone', currentTimezone()),
|
1316
|
+
offset: parseInt(_.get(this, '_submission.metadata.offset', moment().utcOffset()), 10),
|
1317
1317
|
origin: document.location.origin,
|
1318
1318
|
referrer: document.referrer,
|
1319
1319
|
browserName: navigator.appName,
|
@@ -1334,26 +1334,26 @@ export default class Webform extends NestedDataComponent {
|
|
1334
1334
|
}
|
1335
1335
|
const submission = fastCloneDeep(this.submission || {});
|
1336
1336
|
this.setMetadata(submission);
|
1337
|
-
submission.state = options.state || submission.state ||
|
1338
|
-
const isDraft = submission.state ===
|
1339
|
-
this.hook(
|
1337
|
+
submission.state = options.state || submission.state || 'submitted';
|
1338
|
+
const isDraft = submission.state === 'draft';
|
1339
|
+
this.hook('beforeSubmit', { ...submission, component: options.component }, (err, data) => {
|
1340
1340
|
if (err) {
|
1341
1341
|
return reject(err);
|
1342
1342
|
}
|
1343
|
-
submission._vnote = data && data._vnote ? data._vnote :
|
1343
|
+
submission._vnote = data && data._vnote ? data._vnote : '';
|
1344
1344
|
try {
|
1345
1345
|
if (!isDraft && !options.noValidate) {
|
1346
1346
|
if (!submission.data) {
|
1347
|
-
return reject(
|
1347
|
+
return reject('Invalid Submission');
|
1348
1348
|
}
|
1349
1349
|
const errors = this.validate(submission.data, {
|
1350
1350
|
local,
|
1351
1351
|
dirty: true,
|
1352
1352
|
silentCheck: false,
|
1353
|
-
process:
|
1353
|
+
process: 'submit',
|
1354
1354
|
});
|
1355
1355
|
if (errors.length ||
|
1356
|
-
options.beforeSubmitResults?.some((result) => result.status ===
|
1356
|
+
options.beforeSubmitResults?.some((result) => result.status === 'rejected')) {
|
1357
1357
|
return reject(errors);
|
1358
1358
|
}
|
1359
1359
|
}
|
@@ -1362,18 +1362,18 @@ export default class Webform extends NestedDataComponent {
|
|
1362
1362
|
console.error(err);
|
1363
1363
|
}
|
1364
1364
|
this.everyComponent((comp) => {
|
1365
|
-
if (submission._vnote && comp.type ===
|
1365
|
+
if (submission._vnote && comp.type === 'form' && comp.component.reference) {
|
1366
1366
|
_.get(submission.data, local ? comp.paths?.localDataPath : comp.path, {})._vnote = submission._vnote;
|
1367
1367
|
}
|
1368
1368
|
const { persistent } = comp.component;
|
1369
|
-
if (persistent ===
|
1369
|
+
if (persistent === 'client-only') {
|
1370
1370
|
_.unset(submission.data, local ? comp.paths?.localDataPath : comp.path);
|
1371
1371
|
}
|
1372
1372
|
});
|
1373
|
-
this.hook(
|
1373
|
+
this.hook('customValidation', { ...submission, component: options.component }, (err) => {
|
1374
1374
|
if (err) {
|
1375
1375
|
// If string is returned, cast to object.
|
1376
|
-
if (typeof err ===
|
1376
|
+
if (typeof err === 'string') {
|
1377
1377
|
err = {
|
1378
1378
|
message: err,
|
1379
1379
|
};
|
@@ -1387,8 +1387,8 @@ export default class Webform extends NestedDataComponent {
|
|
1387
1387
|
if (this._form && this._form.action) {
|
1388
1388
|
const method = submission.data._id &&
|
1389
1389
|
this._form.action.includes(submission.data._id)
|
1390
|
-
?
|
1391
|
-
:
|
1390
|
+
? 'PUT'
|
1391
|
+
: 'POST';
|
1392
1392
|
return Formio.makeStaticRequest(this._form.action, method, submission, this.formio ? this.formio.options : {})
|
1393
1393
|
.then((result) => resolve({
|
1394
1394
|
submission: result,
|
@@ -1408,8 +1408,8 @@ export default class Webform extends NestedDataComponent {
|
|
1408
1408
|
}
|
1409
1409
|
// If this is an actionUrl, then make sure to save the action and not the submission.
|
1410
1410
|
const submitMethod = submitFormio.actionUrl
|
1411
|
-
?
|
1412
|
-
:
|
1411
|
+
? 'saveAction'
|
1412
|
+
: 'saveSubmission';
|
1413
1413
|
submitFormio[submitMethod](submission)
|
1414
1414
|
.then((result) => resolve({
|
1415
1415
|
submission: result,
|
@@ -1426,14 +1426,14 @@ export default class Webform extends NestedDataComponent {
|
|
1426
1426
|
setServerErrors(error) {
|
1427
1427
|
if (error.details) {
|
1428
1428
|
this.serverErrors = error.details
|
1429
|
-
.filter((err) => (err.level ? err.level ===
|
1429
|
+
.filter((err) => (err.level ? err.level === 'error' : err))
|
1430
1430
|
.map((err) => {
|
1431
1431
|
err.fromServer = true;
|
1432
1432
|
return err;
|
1433
1433
|
});
|
1434
1434
|
}
|
1435
|
-
else if (typeof error ===
|
1436
|
-
this.serverErrors = [{ fromServer: true, level:
|
1435
|
+
else if (typeof error === 'string') {
|
1436
|
+
this.serverErrors = [{ fromServer: true, level: 'error', message: error }];
|
1437
1437
|
}
|
1438
1438
|
}
|
1439
1439
|
executeSubmit(options) {
|
@@ -1491,17 +1491,17 @@ export default class Webform extends NestedDataComponent {
|
|
1491
1491
|
}
|
1492
1492
|
submitUrl(URL, headers) {
|
1493
1493
|
if (!URL) {
|
1494
|
-
return console.warn(
|
1494
|
+
return console.warn(this.t('missingUrl'));
|
1495
1495
|
}
|
1496
1496
|
const submission = this.submission || {};
|
1497
1497
|
const API_URL = URL;
|
1498
1498
|
const settings = {
|
1499
|
-
method:
|
1499
|
+
method: 'POST',
|
1500
1500
|
headers: {},
|
1501
1501
|
};
|
1502
1502
|
if (headers && headers.length > 0) {
|
1503
1503
|
headers.map((e) => {
|
1504
|
-
if (e.header !==
|
1504
|
+
if (e.header !== '' && e.value !== '') {
|
1505
1505
|
settings.headers[e.header] = this.interpolate(e.value, submission);
|
1506
1506
|
}
|
1507
1507
|
});
|
@@ -1511,21 +1511,22 @@ export default class Webform extends NestedDataComponent {
|
|
1511
1511
|
headers: settings.headers,
|
1512
1512
|
})
|
1513
1513
|
.then(() => {
|
1514
|
-
this.emit(
|
1515
|
-
this.setAlert(
|
1514
|
+
this.emit('requestDone');
|
1515
|
+
this.setAlert('success', `<p> ${this.t('success')} </p>`);
|
1516
1516
|
})
|
1517
1517
|
.catch((e) => {
|
1518
|
-
const message = `${e.statusText ? e.statusText :
|
1519
|
-
this.emit(
|
1518
|
+
const message = `${e.statusText ? e.statusText : ''} ${e.status ? e.status : e}`;
|
1519
|
+
this.emit('error', message);
|
1520
1520
|
console.error(message);
|
1521
|
-
this.setAlert(
|
1521
|
+
this.setAlert('danger', `<p> ${message} </p>`);
|
1522
1522
|
return Promise.reject(this.onSubmissionError(e));
|
1523
1523
|
});
|
1524
1524
|
}
|
1525
1525
|
else {
|
1526
|
-
|
1527
|
-
this.
|
1528
|
-
|
1526
|
+
const message = this.t('urlNotAttachedToBtn');
|
1527
|
+
this.emit('error', message);
|
1528
|
+
this.setAlert('warning', message);
|
1529
|
+
return console.warn(message);
|
1529
1530
|
}
|
1530
1531
|
}
|
1531
1532
|
triggerCaptcha() {
|
@@ -1544,7 +1545,7 @@ export default class Webform extends NestedDataComponent {
|
|
1544
1545
|
}
|
1545
1546
|
set nosubmit(value) {
|
1546
1547
|
this._nosubmit = !!value;
|
1547
|
-
this.emit(
|
1548
|
+
this.emit('nosubmit', this._nosubmit);
|
1548
1549
|
}
|
1549
1550
|
get nosubmit() {
|
1550
1551
|
return this._nosubmit || false;
|