@formio/js 5.1.0-dev.6082.6dd4100 → 5.1.0-dev.6086.0b0957a
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 +5 -5
- package/dist/formio.form.min.js +1 -1
- package/dist/formio.full.js +5 -5
- package/dist/formio.full.min.js +1 -1
- package/dist/formio.utils.js +1 -1
- package/dist/formio.utils.min.js +1 -1
- package/lib/cjs/components/_classes/component/Component.d.ts +27 -2
- package/lib/cjs/components/_classes/component/Component.js +62 -32
- package/lib/cjs/components/form/Form.d.ts +0 -1
- package/lib/cjs/components/form/Form.js +12 -20
- package/lib/cjs/components/textfield/TextField.js +2 -2
- package/lib/cjs/utils/utils.d.ts +0 -9
- package/lib/cjs/utils/utils.js +1 -16
- package/lib/cjs/widgets/CalendarWidget.js +1 -6
- package/lib/mjs/components/_classes/component/Component.d.ts +27 -2
- package/lib/mjs/components/_classes/component/Component.js +62 -32
- package/lib/mjs/components/form/Form.d.ts +0 -1
- package/lib/mjs/components/form/Form.js +12 -20
- package/lib/mjs/components/textfield/TextField.js +2 -2
- package/lib/mjs/utils/utils.d.ts +0 -9
- package/lib/mjs/utils/utils.js +0 -14
- package/lib/mjs/widgets/CalendarWidget.js +2 -7
- package/package.json +1 -1
@@ -163,8 +163,18 @@ declare class Component extends Element {
|
|
163
163
|
*/
|
164
164
|
info: any;
|
165
165
|
get componentsMap(): object;
|
166
|
+
/**
|
167
|
+
* Returns if the parent should conditionally clear.
|
168
|
+
*
|
169
|
+
* @returns {boolean} - If the parent should conditionally clear.
|
170
|
+
*/
|
166
171
|
parentShouldConditionallyClear(): boolean;
|
167
172
|
parentConditionallyHidden(): boolean;
|
173
|
+
/**
|
174
|
+
* Returns true if any of the parents default their component "hidden" property to true.
|
175
|
+
* @returns {boolean} - If any parent defaults the hidden property to true.
|
176
|
+
*/
|
177
|
+
anyParentDefaultsHidden(): boolean;
|
168
178
|
set data(value: any);
|
169
179
|
get data(): any;
|
170
180
|
mergeSchema(component?: {}): any;
|
@@ -228,8 +238,23 @@ declare class Component extends Element {
|
|
228
238
|
get visible(): boolean;
|
229
239
|
get logicallyHidden(): any;
|
230
240
|
_logicallyHidden: any;
|
231
|
-
|
232
|
-
|
241
|
+
/**
|
242
|
+
* Determines if the component should clear its value when the root form is pristine.
|
243
|
+
* @returns {boolean} - If the component should clear its value when the root form is pristine.
|
244
|
+
*/
|
245
|
+
shouldConditionallyClearOnPristine(): boolean;
|
246
|
+
/**
|
247
|
+
* Returns if the component should clear its value when conditionally hidden.
|
248
|
+
* @returns {boolean} - If the component should clear its value when conditionally hidden.
|
249
|
+
*/
|
250
|
+
shouldConditionallyClear(): boolean;
|
251
|
+
_conditionallyClear: boolean | undefined;
|
252
|
+
/**
|
253
|
+
* Returns if the component is conditionally hidden.
|
254
|
+
* @returns {boolean} - If the component is conditionally hidden.
|
255
|
+
*/
|
256
|
+
conditionallyHidden(): boolean;
|
257
|
+
_conditionallyHidden: boolean | undefined;
|
233
258
|
set currentForm(instance: any);
|
234
259
|
get currentForm(): any;
|
235
260
|
_currentForm: any;
|
@@ -458,10 +458,16 @@ class Component extends Element_1.default {
|
|
458
458
|
var _a;
|
459
459
|
return ((_a = this.root) === null || _a === void 0 ? void 0 : _a.childComponentsMap) || {};
|
460
460
|
}
|
461
|
+
/**
|
462
|
+
* Returns if the parent should conditionally clear.
|
463
|
+
*
|
464
|
+
* @returns {boolean} - If the parent should conditionally clear.
|
465
|
+
*/
|
461
466
|
parentShouldConditionallyClear() {
|
462
467
|
let currentParent = this.parent;
|
463
468
|
while (currentParent) {
|
464
|
-
if (currentParent.
|
469
|
+
if ((currentParent.allowData && currentParent._conditionallyClear) ||
|
470
|
+
(!currentParent.allowData && currentParent._conditionallyHidden)) {
|
465
471
|
return true;
|
466
472
|
}
|
467
473
|
currentParent = currentParent.parent;
|
@@ -471,7 +477,21 @@ class Component extends Element_1.default {
|
|
471
477
|
parentConditionallyHidden() {
|
472
478
|
let currentParent = this.parent;
|
473
479
|
while (currentParent) {
|
474
|
-
if (currentParent.
|
480
|
+
if (currentParent._conditionallyHidden) {
|
481
|
+
return true;
|
482
|
+
}
|
483
|
+
currentParent = currentParent.parent;
|
484
|
+
}
|
485
|
+
return false;
|
486
|
+
}
|
487
|
+
/**
|
488
|
+
* Returns true if any of the parents default their component "hidden" property to true.
|
489
|
+
* @returns {boolean} - If any parent defaults the hidden property to true.
|
490
|
+
*/
|
491
|
+
anyParentDefaultsHidden() {
|
492
|
+
let currentParent = this.parent;
|
493
|
+
while (currentParent) {
|
494
|
+
if (currentParent.component.hidden) {
|
475
495
|
return true;
|
476
496
|
}
|
477
497
|
currentParent = currentParent.parent;
|
@@ -689,48 +709,58 @@ class Component extends Element_1.default {
|
|
689
709
|
}
|
690
710
|
return this._logicallyHidden;
|
691
711
|
}
|
692
|
-
|
712
|
+
/**
|
713
|
+
* Determines if the component should clear its value when the root form is pristine.
|
714
|
+
* @returns {boolean} - If the component should clear its value when the root form is pristine.
|
715
|
+
*/
|
716
|
+
shouldConditionallyClearOnPristine() {
|
717
|
+
// If the form is pristine, we should NOT clear the value of a conditionally hidden child component
|
718
|
+
// of a layout component that defaults to hidden using the "hidden" component property.
|
719
|
+
return !this.anyParentDefaultsHidden();
|
720
|
+
}
|
721
|
+
/**
|
722
|
+
* Returns if the component should clear its value when conditionally hidden.
|
723
|
+
* @returns {boolean} - If the component should clear its value when conditionally hidden.
|
724
|
+
*/
|
725
|
+
shouldConditionallyClear() {
|
693
726
|
// Skip if this component has clearOnHide set to false.
|
694
727
|
if (this.component.clearOnHide === false) {
|
695
|
-
|
728
|
+
this._conditionallyClear = false;
|
729
|
+
return this._conditionallyClear;
|
696
730
|
}
|
697
731
|
// If the component is logically hidden, then it is conditionally hidden and should clear.
|
698
732
|
if (this.logicallyHidden) {
|
699
|
-
|
733
|
+
this._conditionallyClear = true;
|
734
|
+
return this._conditionallyClear;
|
700
735
|
}
|
701
736
|
// If we have a condition and it is not conditionally visible, the it should conditionally clear.
|
702
|
-
if (this.hasCondition() &&
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
return false;
|
708
|
-
}
|
709
|
-
// If this component has a set value, then it should ONLY clear if a parent is hidden
|
710
|
-
// and has the clearOnHide set to true.
|
711
|
-
if (this.hasSetValue) {
|
712
|
-
return this.parentShouldConditionallyClear();
|
737
|
+
if (this.hasCondition() &&
|
738
|
+
!this.conditionallyVisible() &&
|
739
|
+
(!this.rootPristine || this.shouldConditionallyClearOnPristine())) {
|
740
|
+
this._conditionallyClear = true;
|
741
|
+
return this._conditionallyClear;
|
713
742
|
}
|
714
|
-
|
715
|
-
return this.
|
743
|
+
this._conditionallyClear = this.hasSetValue ? false : this.parentShouldConditionallyClear();
|
744
|
+
return this._conditionallyClear;
|
716
745
|
}
|
717
|
-
|
746
|
+
/**
|
747
|
+
* Returns if the component is conditionally hidden.
|
748
|
+
* @returns {boolean} - If the component is conditionally hidden.
|
749
|
+
*/
|
750
|
+
conditionallyHidden() {
|
751
|
+
// If it is logically hidden, then it is conditionally hidden.
|
718
752
|
if (this.logicallyHidden) {
|
719
|
-
|
720
|
-
|
721
|
-
if (!this.hasCondition() && !skipParent) {
|
722
|
-
return this.parentConditionallyHidden();
|
753
|
+
this._conditionallyHidden = true;
|
754
|
+
return this._conditionallyHidden;
|
723
755
|
}
|
724
|
-
//
|
725
|
-
if (!this.conditionallyVisible()) {
|
726
|
-
|
727
|
-
|
728
|
-
if (skipParent) {
|
729
|
-
// Stop recurrsion for the parent checks.
|
730
|
-
return false;
|
756
|
+
// If it has a condition, and is not conditionally visible, then it is conditionally hidden.
|
757
|
+
if (this.hasCondition() && !this.conditionallyVisible()) {
|
758
|
+
this._conditionallyHidden = true;
|
759
|
+
return this._conditionallyHidden;
|
731
760
|
}
|
732
|
-
//
|
733
|
-
|
761
|
+
// It is conditionally hidden if its parent is conditionally hidden.
|
762
|
+
this._conditionallyHidden = this.parentConditionallyHidden();
|
763
|
+
return this._conditionallyHidden;
|
734
764
|
}
|
735
765
|
get currentForm() {
|
736
766
|
return this._currentForm;
|
@@ -98,7 +98,6 @@ export default class FormComponent extends Component {
|
|
98
98
|
* @returns {void}
|
99
99
|
*/
|
100
100
|
onSetSubFormValue(submission: object | null | undefined, flags: object | null | undefined): void;
|
101
|
-
areAllComponentsEmpty(data: any): boolean;
|
102
101
|
updateSubFormVisibility(): void;
|
103
102
|
/**
|
104
103
|
* Determines if this form is a Nested Wizard
|
@@ -101,6 +101,9 @@ class FormComponent extends Component_1.default {
|
|
101
101
|
}
|
102
102
|
return this.createSubForm();
|
103
103
|
}
|
104
|
+
shouldConditionallyClearOnPristine() {
|
105
|
+
return !this.hasSetValue && super.shouldConditionallyClearOnPristine();
|
106
|
+
}
|
104
107
|
get dataReady() {
|
105
108
|
var _a;
|
106
109
|
return ((_a = this.subForm) === null || _a === void 0 ? void 0 : _a.dataReady) || this.subFormReady || Promise.resolve();
|
@@ -290,11 +293,13 @@ class FormComponent extends Component_1.default {
|
|
290
293
|
}
|
291
294
|
this.subForm.attach(element);
|
292
295
|
this.valueChanged = this.hasSetValue;
|
293
|
-
if (!this.
|
294
|
-
this.
|
295
|
-
|
296
|
-
|
297
|
-
|
296
|
+
if (!this.shouldConditionallyClear()) {
|
297
|
+
if (!this.valueChanged && this.dataValue.state !== 'submitted') {
|
298
|
+
this.setDefaultValue();
|
299
|
+
}
|
300
|
+
else {
|
301
|
+
this.restoreValue();
|
302
|
+
}
|
298
303
|
}
|
299
304
|
}
|
300
305
|
if (!this.builderMode && this.component.modalEdit) {
|
@@ -411,7 +416,7 @@ class FormComponent extends Component_1.default {
|
|
411
416
|
lodash_1.default.assign(componentsMap, formComponentsMap);
|
412
417
|
this.component.components = this.subForm.components.map((comp) => comp.component);
|
413
418
|
this.subForm.on('change', () => {
|
414
|
-
if (this.subForm) {
|
419
|
+
if (this.subForm && !this.shouldConditionallyClear()) {
|
415
420
|
this.dataValue = this.subForm.getValue();
|
416
421
|
this.triggerChange({
|
417
422
|
noEmit: true
|
@@ -679,20 +684,7 @@ class FormComponent extends Component_1.default {
|
|
679
684
|
}
|
680
685
|
}
|
681
686
|
isEmpty(value = this.dataValue) {
|
682
|
-
return value === null || lodash_1.default.isEqual(value, this.emptyValue)
|
683
|
-
}
|
684
|
-
areAllComponentsEmpty(data) {
|
685
|
-
let res = true;
|
686
|
-
if (this.subForm) {
|
687
|
-
this.subForm.everyComponent((comp) => {
|
688
|
-
const componentValue = lodash_1.default.get(data, comp.key);
|
689
|
-
res &= comp.isEmpty(componentValue);
|
690
|
-
});
|
691
|
-
}
|
692
|
-
else {
|
693
|
-
res = false;
|
694
|
-
}
|
695
|
-
return res;
|
687
|
+
return value === null || lodash_1.default.isEqual(value, this.emptyValue);
|
696
688
|
}
|
697
689
|
getValue() {
|
698
690
|
if (this.subForm) {
|
@@ -102,8 +102,8 @@ class TextFieldComponent extends Input_1.default {
|
|
102
102
|
if (((_c = this.component.widget) === null || _c === void 0 ? void 0 : _c.type) === 'calendar') {
|
103
103
|
this.component.widget = Object.assign(Object.assign({}, this.component.widget), { readOnly: this.options.readOnly, timezone,
|
104
104
|
displayInTimezone, locale: this.component.widget.locale || this.options.language, saveAs: 'text' });
|
105
|
-
// update originalComponent to include widget settings after component initialization
|
106
|
-
// originalComponent is used to restore the component (and widget) after evaluating field logic
|
105
|
+
// update originalComponent to include widget settings after component initialization
|
106
|
+
// originalComponent is used to restore the component (and widget) after evaluating field logic
|
107
107
|
this.originalComponent = FormioUtils.fastCloneDeep(this.component);
|
108
108
|
}
|
109
109
|
}
|
package/lib/cjs/utils/utils.d.ts
CHANGED
@@ -490,15 +490,6 @@ export function getFocusableElements(element: HTMLElement): NodeList<HTMLElement
|
|
490
490
|
* @returns {Array<string>|null} - The saved types for the component
|
491
491
|
*/
|
492
492
|
export function getComponentSavedTypes(fullSchema: import('@formio/core').Component): Array<string> | null;
|
493
|
-
/**
|
494
|
-
* Checks if a string has timezone information encoded in it
|
495
|
-
* Example: 2024-01-01T00:00:00Z -> true
|
496
|
-
* Example: 2024-01-01T00:00:00+03:00 -> true
|
497
|
-
* Example: 2011-05-03T00:00:00 -> false
|
498
|
-
* @param {string} value the string value to check
|
499
|
-
* @returns {boolean} if value has encoded timezone
|
500
|
-
*/
|
501
|
-
export function hasEncodedTimezone(value: string): boolean;
|
502
493
|
export * from "./formUtils";
|
503
494
|
/**
|
504
495
|
* Map values through unfold and return first non-nil value.
|
package/lib/cjs/utils/utils.js
CHANGED
@@ -19,7 +19,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
19
19
|
};
|
20
20
|
Object.defineProperty(exports, "__esModule", { value: true });
|
21
21
|
exports.firstNonNil = exports.unfold = exports.bootstrapVersion = exports.uniqueKey = exports.iterateKey = exports.delay = exports.fieldData = exports.getCurrencyAffixes = exports.getNumberDecimalLimit = exports.getNumberSeparators = exports.matchInputMask = exports.unmaskValue = exports.getInputMask = exports.convertFormatToMask = exports.convertFormatToMoment = exports.convertFormatToFlatpickr = exports.getLocaleDateFormatInfo = exports.formatOffset = exports.formatDate = exports.momentDate = exports.loadZones = exports.shouldLoadZones = exports.zonesLoaded = exports.offsetDate = exports.currentTimezone = exports.isValidDate = exports.getDateSetting = exports.guid = exports.uniqueName = exports.convertStringToHTMLElement = exports.unescapeHTML = exports.removeHTML = exports.setActionProperty = exports.checkTrigger = exports.checkCondition = exports.checkJsonConditional = exports.checkCustomConditional = exports.getComponentActualValue = exports.checkSimpleConditional = exports.checkCalculated = exports.isMongoId = exports.boolValue = exports.getScriptPlugin = exports.getElementRect = exports.getPropertyValue = exports.getRandomComponentId = exports.evaluate = exports.moment = exports.ConditionOperators = exports.jsonLogic = void 0;
|
22
|
-
exports.
|
22
|
+
exports.interpolateErrors = exports.getComponentSavedTypes = exports.componentValueTypes = exports._ = exports.getFocusableElements = exports.isPromise = exports.getDataParentComponent = exports.getComponentPath = exports.getComponentPathWithoutIndicies = exports.getBrowserInfo = exports.getIEBrowserVersion = exports.round = exports.getStringFromComponentPath = exports.isChildOf = exports.getArrayFromComponentPath = exports.isInputComponent = exports.interpolate = exports.Evaluator = exports.fastCloneDeep = exports.sanitize = exports.translateHTMLTemplate = exports.getContextButtons = exports.getContextComponents = exports.observeOverload = exports.withSwitch = void 0;
|
23
23
|
const lodash_1 = __importDefault(require("lodash"));
|
24
24
|
exports._ = lodash_1.default;
|
25
25
|
const json_logic_js_1 = __importDefault(require("json-logic-js"));
|
@@ -1646,18 +1646,3 @@ const interpolateErrors = (component, errors, interpolateFn) => {
|
|
1646
1646
|
});
|
1647
1647
|
};
|
1648
1648
|
exports.interpolateErrors = interpolateErrors;
|
1649
|
-
/**
|
1650
|
-
* Checks if a string has timezone information encoded in it
|
1651
|
-
* Example: 2024-01-01T00:00:00Z -> true
|
1652
|
-
* Example: 2024-01-01T00:00:00+03:00 -> true
|
1653
|
-
* Example: 2011-05-03T00:00:00 -> false
|
1654
|
-
* @param {string} value the string value to check
|
1655
|
-
* @returns {boolean} if value has encoded timezone
|
1656
|
-
*/
|
1657
|
-
function hasEncodedTimezone(value) {
|
1658
|
-
if (typeof value !== 'string') {
|
1659
|
-
return false;
|
1660
|
-
}
|
1661
|
-
return (value.substring(value.length - 1) === 'z' || value.substring(value.length - 1) === 'Z' || value.match(/[+|-][0-9]+:[0-9]+/));
|
1662
|
-
}
|
1663
|
-
exports.hasEncodedTimezone = hasEncodedTimezone;
|
@@ -286,11 +286,6 @@ class CalendarWidget extends InputWidget_1.default {
|
|
286
286
|
value = value ? (0, utils_1.formatDate)(this.timezonesUrl, value, (0, utils_1.convertFormatToMoment)(this.settings.format), this.timezone, (0, utils_1.convertFormatToMoment)(this.valueMomentFormat)) : value;
|
287
287
|
return super.setValue(value);
|
288
288
|
}
|
289
|
-
// If the component is a textfield that does not have timezone information included in the string value then skip
|
290
|
-
// the timezone offset
|
291
|
-
if (this.component.type === 'textfield' && !(utils_1.hasEncodedTimezone)(value)) {
|
292
|
-
this.settings.skipOffset = true;
|
293
|
-
}
|
294
289
|
const zonesLoading = this.loadZones();
|
295
290
|
if (value) {
|
296
291
|
if (!saveAsText && this.settings.readOnly && !zonesLoading) {
|
@@ -458,7 +453,7 @@ class CalendarWidget extends InputWidget_1.default {
|
|
458
453
|
return (date, format) => {
|
459
454
|
// Only format this if this is the altFormat and the form is readOnly.
|
460
455
|
if (this.settings.readOnly && (format === this.settings.altFormat)) {
|
461
|
-
if (!this.settings.enableTime || this.loadZones()
|
456
|
+
if (!this.settings.enableTime || this.loadZones()) {
|
462
457
|
return Flatpickr.formatDate(date, format);
|
463
458
|
}
|
464
459
|
const currentValue = new Date(this.getValue());
|
@@ -163,8 +163,18 @@ declare class Component extends Element {
|
|
163
163
|
*/
|
164
164
|
info: any;
|
165
165
|
get componentsMap(): object;
|
166
|
+
/**
|
167
|
+
* Returns if the parent should conditionally clear.
|
168
|
+
*
|
169
|
+
* @returns {boolean} - If the parent should conditionally clear.
|
170
|
+
*/
|
166
171
|
parentShouldConditionallyClear(): boolean;
|
167
172
|
parentConditionallyHidden(): boolean;
|
173
|
+
/**
|
174
|
+
* Returns true if any of the parents default their component "hidden" property to true.
|
175
|
+
* @returns {boolean} - If any parent defaults the hidden property to true.
|
176
|
+
*/
|
177
|
+
anyParentDefaultsHidden(): boolean;
|
168
178
|
set data(value: any);
|
169
179
|
get data(): any;
|
170
180
|
mergeSchema(component?: {}): any;
|
@@ -228,8 +238,23 @@ declare class Component extends Element {
|
|
228
238
|
get visible(): boolean;
|
229
239
|
get logicallyHidden(): any;
|
230
240
|
_logicallyHidden: any;
|
231
|
-
|
232
|
-
|
241
|
+
/**
|
242
|
+
* Determines if the component should clear its value when the root form is pristine.
|
243
|
+
* @returns {boolean} - If the component should clear its value when the root form is pristine.
|
244
|
+
*/
|
245
|
+
shouldConditionallyClearOnPristine(): boolean;
|
246
|
+
/**
|
247
|
+
* Returns if the component should clear its value when conditionally hidden.
|
248
|
+
* @returns {boolean} - If the component should clear its value when conditionally hidden.
|
249
|
+
*/
|
250
|
+
shouldConditionallyClear(): boolean;
|
251
|
+
_conditionallyClear: boolean | undefined;
|
252
|
+
/**
|
253
|
+
* Returns if the component is conditionally hidden.
|
254
|
+
* @returns {boolean} - If the component is conditionally hidden.
|
255
|
+
*/
|
256
|
+
conditionallyHidden(): boolean;
|
257
|
+
_conditionallyHidden: boolean | undefined;
|
233
258
|
set currentForm(instance: any);
|
234
259
|
get currentForm(): any;
|
235
260
|
_currentForm: any;
|
@@ -422,10 +422,16 @@ export default class Component extends Element {
|
|
422
422
|
get componentsMap() {
|
423
423
|
return this.root?.childComponentsMap || {};
|
424
424
|
}
|
425
|
+
/**
|
426
|
+
* Returns if the parent should conditionally clear.
|
427
|
+
*
|
428
|
+
* @returns {boolean} - If the parent should conditionally clear.
|
429
|
+
*/
|
425
430
|
parentShouldConditionallyClear() {
|
426
431
|
let currentParent = this.parent;
|
427
432
|
while (currentParent) {
|
428
|
-
if (currentParent.
|
433
|
+
if ((currentParent.allowData && currentParent._conditionallyClear) ||
|
434
|
+
(!currentParent.allowData && currentParent._conditionallyHidden)) {
|
429
435
|
return true;
|
430
436
|
}
|
431
437
|
currentParent = currentParent.parent;
|
@@ -435,7 +441,21 @@ export default class Component extends Element {
|
|
435
441
|
parentConditionallyHidden() {
|
436
442
|
let currentParent = this.parent;
|
437
443
|
while (currentParent) {
|
438
|
-
if (currentParent.
|
444
|
+
if (currentParent._conditionallyHidden) {
|
445
|
+
return true;
|
446
|
+
}
|
447
|
+
currentParent = currentParent.parent;
|
448
|
+
}
|
449
|
+
return false;
|
450
|
+
}
|
451
|
+
/**
|
452
|
+
* Returns true if any of the parents default their component "hidden" property to true.
|
453
|
+
* @returns {boolean} - If any parent defaults the hidden property to true.
|
454
|
+
*/
|
455
|
+
anyParentDefaultsHidden() {
|
456
|
+
let currentParent = this.parent;
|
457
|
+
while (currentParent) {
|
458
|
+
if (currentParent.component.hidden) {
|
439
459
|
return true;
|
440
460
|
}
|
441
461
|
currentParent = currentParent.parent;
|
@@ -653,48 +673,58 @@ export default class Component extends Element {
|
|
653
673
|
}
|
654
674
|
return this._logicallyHidden;
|
655
675
|
}
|
656
|
-
|
676
|
+
/**
|
677
|
+
* Determines if the component should clear its value when the root form is pristine.
|
678
|
+
* @returns {boolean} - If the component should clear its value when the root form is pristine.
|
679
|
+
*/
|
680
|
+
shouldConditionallyClearOnPristine() {
|
681
|
+
// If the form is pristine, we should NOT clear the value of a conditionally hidden child component
|
682
|
+
// of a layout component that defaults to hidden using the "hidden" component property.
|
683
|
+
return !this.anyParentDefaultsHidden();
|
684
|
+
}
|
685
|
+
/**
|
686
|
+
* Returns if the component should clear its value when conditionally hidden.
|
687
|
+
* @returns {boolean} - If the component should clear its value when conditionally hidden.
|
688
|
+
*/
|
689
|
+
shouldConditionallyClear() {
|
657
690
|
// Skip if this component has clearOnHide set to false.
|
658
691
|
if (this.component.clearOnHide === false) {
|
659
|
-
|
692
|
+
this._conditionallyClear = false;
|
693
|
+
return this._conditionallyClear;
|
660
694
|
}
|
661
695
|
// If the component is logically hidden, then it is conditionally hidden and should clear.
|
662
696
|
if (this.logicallyHidden) {
|
663
|
-
|
697
|
+
this._conditionallyClear = true;
|
698
|
+
return this._conditionallyClear;
|
664
699
|
}
|
665
700
|
// If we have a condition and it is not conditionally visible, the it should conditionally clear.
|
666
|
-
if (this.hasCondition() &&
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
return false;
|
672
|
-
}
|
673
|
-
// If this component has a set value, then it should ONLY clear if a parent is hidden
|
674
|
-
// and has the clearOnHide set to true.
|
675
|
-
if (this.hasSetValue) {
|
676
|
-
return this.parentShouldConditionallyClear();
|
701
|
+
if (this.hasCondition() &&
|
702
|
+
!this.conditionallyVisible() &&
|
703
|
+
(!this.rootPristine || this.shouldConditionallyClearOnPristine())) {
|
704
|
+
this._conditionallyClear = true;
|
705
|
+
return this._conditionallyClear;
|
677
706
|
}
|
678
|
-
|
679
|
-
return this.
|
707
|
+
this._conditionallyClear = this.hasSetValue ? false : this.parentShouldConditionallyClear();
|
708
|
+
return this._conditionallyClear;
|
680
709
|
}
|
681
|
-
|
710
|
+
/**
|
711
|
+
* Returns if the component is conditionally hidden.
|
712
|
+
* @returns {boolean} - If the component is conditionally hidden.
|
713
|
+
*/
|
714
|
+
conditionallyHidden() {
|
715
|
+
// If it is logically hidden, then it is conditionally hidden.
|
682
716
|
if (this.logicallyHidden) {
|
683
|
-
|
684
|
-
|
685
|
-
if (!this.hasCondition() && !skipParent) {
|
686
|
-
return this.parentConditionallyHidden();
|
717
|
+
this._conditionallyHidden = true;
|
718
|
+
return this._conditionallyHidden;
|
687
719
|
}
|
688
|
-
//
|
689
|
-
if (!this.conditionallyVisible()) {
|
690
|
-
|
691
|
-
|
692
|
-
if (skipParent) {
|
693
|
-
// Stop recurrsion for the parent checks.
|
694
|
-
return false;
|
720
|
+
// If it has a condition, and is not conditionally visible, then it is conditionally hidden.
|
721
|
+
if (this.hasCondition() && !this.conditionallyVisible()) {
|
722
|
+
this._conditionallyHidden = true;
|
723
|
+
return this._conditionallyHidden;
|
695
724
|
}
|
696
|
-
//
|
697
|
-
|
725
|
+
// It is conditionally hidden if its parent is conditionally hidden.
|
726
|
+
this._conditionallyHidden = this.parentConditionallyHidden();
|
727
|
+
return this._conditionallyHidden;
|
698
728
|
}
|
699
729
|
get currentForm() {
|
700
730
|
return this._currentForm;
|
@@ -98,7 +98,6 @@ export default class FormComponent extends Component {
|
|
98
98
|
* @returns {void}
|
99
99
|
*/
|
100
100
|
onSetSubFormValue(submission: object | null | undefined, flags: object | null | undefined): void;
|
101
|
-
areAllComponentsEmpty(data: any): boolean;
|
102
101
|
updateSubFormVisibility(): void;
|
103
102
|
/**
|
104
103
|
* Determines if this form is a Nested Wizard
|
@@ -96,6 +96,9 @@ export default class FormComponent extends Component {
|
|
96
96
|
}
|
97
97
|
return this.createSubForm();
|
98
98
|
}
|
99
|
+
shouldConditionallyClearOnPristine() {
|
100
|
+
return !this.hasSetValue && super.shouldConditionallyClearOnPristine();
|
101
|
+
}
|
99
102
|
get dataReady() {
|
100
103
|
return this.subForm?.dataReady || this.subFormReady || Promise.resolve();
|
101
104
|
}
|
@@ -286,11 +289,13 @@ export default class FormComponent extends Component {
|
|
286
289
|
}
|
287
290
|
this.subForm.attach(element);
|
288
291
|
this.valueChanged = this.hasSetValue;
|
289
|
-
if (!this.
|
290
|
-
this.
|
291
|
-
|
292
|
-
|
293
|
-
|
292
|
+
if (!this.shouldConditionallyClear()) {
|
293
|
+
if (!this.valueChanged && this.dataValue.state !== 'submitted') {
|
294
|
+
this.setDefaultValue();
|
295
|
+
}
|
296
|
+
else {
|
297
|
+
this.restoreValue();
|
298
|
+
}
|
294
299
|
}
|
295
300
|
}
|
296
301
|
if (!this.builderMode && this.component.modalEdit) {
|
@@ -405,7 +410,7 @@ export default class FormComponent extends Component {
|
|
405
410
|
_.assign(componentsMap, formComponentsMap);
|
406
411
|
this.component.components = this.subForm.components.map((comp) => comp.component);
|
407
412
|
this.subForm.on('change', () => {
|
408
|
-
if (this.subForm) {
|
413
|
+
if (this.subForm && !this.shouldConditionallyClear()) {
|
409
414
|
this.dataValue = this.subForm.getValue();
|
410
415
|
this.triggerChange({
|
411
416
|
noEmit: true
|
@@ -668,20 +673,7 @@ export default class FormComponent extends Component {
|
|
668
673
|
}
|
669
674
|
}
|
670
675
|
isEmpty(value = this.dataValue) {
|
671
|
-
return value === null || _.isEqual(value, this.emptyValue)
|
672
|
-
}
|
673
|
-
areAllComponentsEmpty(data) {
|
674
|
-
let res = true;
|
675
|
-
if (this.subForm) {
|
676
|
-
this.subForm.everyComponent((comp) => {
|
677
|
-
const componentValue = _.get(data, comp.key);
|
678
|
-
res &= comp.isEmpty(componentValue);
|
679
|
-
});
|
680
|
-
}
|
681
|
-
else {
|
682
|
-
res = false;
|
683
|
-
}
|
684
|
-
return res;
|
676
|
+
return value === null || _.isEqual(value, this.emptyValue);
|
685
677
|
}
|
686
678
|
getValue() {
|
687
679
|
if (this.subForm) {
|
@@ -86,8 +86,8 @@ export default class TextFieldComponent extends Input {
|
|
86
86
|
locale: this.component.widget.locale || this.options.language,
|
87
87
|
saveAs: 'text'
|
88
88
|
};
|
89
|
-
// update originalComponent to include widget settings after component initialization
|
90
|
-
// originalComponent is used to restore the component (and widget) after evaluating field logic
|
89
|
+
// update originalComponent to include widget settings after component initialization
|
90
|
+
// originalComponent is used to restore the component (and widget) after evaluating field logic
|
91
91
|
this.originalComponent = FormioUtils.fastCloneDeep(this.component);
|
92
92
|
}
|
93
93
|
}
|
package/lib/mjs/utils/utils.d.ts
CHANGED
@@ -490,15 +490,6 @@ export function getFocusableElements(element: HTMLElement): NodeList<HTMLElement
|
|
490
490
|
* @returns {Array<string>|null} - The saved types for the component
|
491
491
|
*/
|
492
492
|
export function getComponentSavedTypes(fullSchema: import('@formio/core').Component): Array<string> | null;
|
493
|
-
/**
|
494
|
-
* Checks if a string has timezone information encoded in it
|
495
|
-
* Example: 2024-01-01T00:00:00Z -> true
|
496
|
-
* Example: 2024-01-01T00:00:00+03:00 -> true
|
497
|
-
* Example: 2011-05-03T00:00:00 -> false
|
498
|
-
* @param {string} value the string value to check
|
499
|
-
* @returns {boolean} if value has encoded timezone
|
500
|
-
*/
|
501
|
-
export function hasEncodedTimezone(value: string): boolean;
|
502
493
|
export * from "./formUtils";
|
503
494
|
/**
|
504
495
|
* Map values through unfold and return first non-nil value.
|
package/lib/mjs/utils/utils.js
CHANGED
@@ -1554,17 +1554,3 @@ export const interpolateErrors = (component, errors, interpolateFn) => {
|
|
1554
1554
|
return { ...error, message: unescapeHTML(interpolateFn(toInterpolate, context)), context: { ...context } };
|
1555
1555
|
});
|
1556
1556
|
};
|
1557
|
-
/**
|
1558
|
-
* Checks if a string has timezone information encoded in it
|
1559
|
-
* Example: 2024-01-01T00:00:00Z -> true
|
1560
|
-
* Example: 2024-01-01T00:00:00+03:00 -> true
|
1561
|
-
* Example: 2011-05-03T00:00:00 -> false
|
1562
|
-
* @param {string} value the string value to check
|
1563
|
-
* @returns {boolean} if value has encoded timezone
|
1564
|
-
*/
|
1565
|
-
export function hasEncodedTimezone(value) {
|
1566
|
-
if (typeof value !== 'string') {
|
1567
|
-
return false;
|
1568
|
-
}
|
1569
|
-
return (value.substring(value.length - 1) === 'z' || value.substring(value.length - 1) === 'Z' || value.match(/[+|-][0-9]+:[0-9]+/));
|
1570
|
-
}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import { Formio } from '../Formio';
|
2
2
|
import InputWidget from './InputWidget';
|
3
|
-
import { convertFormatToFlatpickr, convertFormatToMask, convertFormatToMoment, formatDate, formatOffset, getBrowserInfo, getDateSetting, getLocaleDateFormatInfo, momentDate, zonesLoaded, shouldLoadZones, loadZones,
|
3
|
+
import { convertFormatToFlatpickr, convertFormatToMask, convertFormatToMoment, formatDate, formatOffset, getBrowserInfo, getDateSetting, getLocaleDateFormatInfo, momentDate, zonesLoaded, shouldLoadZones, loadZones, } from '../utils/utils';
|
4
4
|
import moment from 'moment';
|
5
5
|
import _ from 'lodash';
|
6
6
|
const DEFAULT_FORMAT = 'yyyy-MM-dd hh:mm a';
|
@@ -278,11 +278,6 @@ export default class CalendarWidget extends InputWidget {
|
|
278
278
|
value = value ? formatDate(this.timezonesUrl, value, convertFormatToMoment(this.settings.format), this.timezone, convertFormatToMoment(this.valueMomentFormat)) : value;
|
279
279
|
return super.setValue(value);
|
280
280
|
}
|
281
|
-
// If the component is a textfield that does not have timezone information included in the string value then skip
|
282
|
-
// the timezone offset
|
283
|
-
if (this.component.type === 'textfield' && !(hasEncodedTimezone)(value)) {
|
284
|
-
this.settings.skipOffset = true;
|
285
|
-
}
|
286
281
|
const zonesLoading = this.loadZones();
|
287
282
|
if (value) {
|
288
283
|
if (!saveAsText && this.settings.readOnly && !zonesLoading) {
|
@@ -448,7 +443,7 @@ export default class CalendarWidget extends InputWidget {
|
|
448
443
|
return (date, format) => {
|
449
444
|
// Only format this if this is the altFormat and the form is readOnly.
|
450
445
|
if (this.settings.readOnly && (format === this.settings.altFormat)) {
|
451
|
-
if (!this.settings.enableTime || this.loadZones()
|
446
|
+
if (!this.settings.enableTime || this.loadZones()) {
|
452
447
|
return Flatpickr.formatDate(date, format);
|
453
448
|
}
|
454
449
|
const currentValue = new Date(this.getValue());
|