@formio/js 5.6.0 → 5.7.0-api912.2
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.builder.css +5 -5
- package/dist/formio.builder.min.css +1 -1
- package/dist/formio.embed.js +1 -1
- package/dist/formio.embed.min.js +1 -1
- package/dist/formio.embed.min.js.LICENSE.txt +1 -1
- package/dist/formio.form.css +5 -5
- package/dist/formio.form.js +5218 -5191
- package/dist/formio.form.min.css +1 -1
- package/dist/formio.form.min.js +1 -1
- package/dist/formio.form.min.js.LICENSE.txt +3 -1
- package/dist/formio.full.css +5 -5
- package/dist/formio.full.js +6073 -6046
- package/dist/formio.full.min.css +1 -1
- package/dist/formio.full.min.js +1 -1
- package/dist/formio.full.min.js.LICENSE.txt +3 -1
- package/dist/formio.js +1215 -1188
- package/dist/formio.min.js +1 -1
- package/dist/formio.min.js.LICENSE.txt +3 -1
- package/dist/formio.utils.js +1106 -1079
- package/dist/formio.utils.min.js +1 -1
- package/dist/formio.utils.min.js.LICENSE.txt +3 -1
- package/lib/cjs/Embed.js +38 -25
- package/lib/cjs/Form.d.ts +8 -2
- package/lib/cjs/Form.js +1 -1
- package/lib/cjs/Formio.js +1 -1
- package/lib/cjs/PDF.d.ts +1 -0
- package/lib/cjs/PDF.js +21 -5
- package/lib/cjs/PDFBuilder.d.ts +1 -0
- package/lib/cjs/PDFBuilder.js +1 -0
- package/lib/cjs/Webform.d.ts +13 -1
- package/lib/cjs/Webform.js +79 -26
- package/lib/cjs/Wizard.d.ts +1 -1
- package/lib/cjs/Wizard.js +12 -6
- package/lib/cjs/components/Components.js +1 -5
- package/lib/cjs/components/_classes/component/Component.d.ts +14 -0
- package/lib/cjs/components/_classes/component/Component.js +33 -65
- package/lib/cjs/components/_classes/nested/NestedComponent.form.js +13 -0
- package/lib/cjs/components/_classes/nested/NestedComponent.js +10 -8
- package/lib/cjs/components/content/editForm/Content.edit.display.js +8 -0
- package/lib/cjs/components/currency/editForm/Currency.edit.display.js +20 -0
- package/lib/cjs/components/datagrid/DataGrid.js +2 -6
- package/lib/cjs/components/day/editForm/Day.edit.display.js +8 -0
- package/lib/cjs/components/editgrid/EditGrid.d.ts +1 -0
- package/lib/cjs/components/editgrid/EditGrid.js +22 -2
- package/lib/cjs/components/email/editForm/Email.edit.display.js +12 -0
- package/lib/cjs/components/fieldset/editForm/Fieldset.edit.display.js +8 -0
- package/lib/cjs/components/file/editForm/File.edit.file.js +1 -1
- package/lib/cjs/components/form/Form.js +21 -1
- package/lib/cjs/components/hidden/Hidden.d.ts +0 -1
- package/lib/cjs/components/hidden/Hidden.js +1 -1
- package/lib/cjs/components/hidden/editForm/Hidden.edit.display.js +8 -0
- package/lib/cjs/components/html/editForm/HTML.edit.display.js +8 -0
- package/lib/cjs/components/number/Number.d.ts +11 -0
- package/lib/cjs/components/number/Number.js +35 -0
- package/lib/cjs/components/number/editForm/Number.edit.display.js +12 -0
- package/lib/cjs/components/password/editForm/Password.edit.display.js +12 -0
- package/lib/cjs/components/phonenumber/PhoneNumber.form.js +8 -0
- package/lib/cjs/components/select/editForm/Select.edit.data.d.ts +1 -1
- package/lib/cjs/components/select/editForm/Select.edit.data.js +1 -0
- package/lib/cjs/components/tabs/editForm/Tabs.edit.display.js +8 -0
- package/lib/cjs/components/textarea/editForm/TextArea.edit.display.js +12 -0
- package/lib/cjs/components/url/editForm/Url.edit.display.js +12 -0
- package/lib/cjs/components/well/editForm/Well.edit.display.js +8 -0
- package/lib/cjs/package.json +1 -1
- package/lib/cjs/utils/formUtils.d.ts +3 -0
- package/lib/cjs/utils/formUtils.js +5 -2
- package/lib/cjs/utils/index.d.ts +3 -0
- package/lib/cjs/utils/utils.js +6 -18
- package/lib/mjs/Embed.js +37 -24
- package/lib/mjs/Form.d.ts +8 -2
- package/lib/mjs/Form.js +1 -1
- package/lib/mjs/Formio.js +1 -1
- package/lib/mjs/PDF.d.ts +1 -0
- package/lib/mjs/PDF.js +21 -5
- package/lib/mjs/PDFBuilder.d.ts +1 -0
- package/lib/mjs/PDFBuilder.js +1 -0
- package/lib/mjs/Webform.d.ts +13 -1
- package/lib/mjs/Webform.js +75 -24
- package/lib/mjs/Wizard.d.ts +1 -1
- package/lib/mjs/Wizard.js +12 -6
- package/lib/mjs/components/Components.js +1 -5
- package/lib/mjs/components/_classes/component/Component.d.ts +14 -0
- package/lib/mjs/components/_classes/component/Component.js +33 -65
- package/lib/mjs/components/_classes/nested/NestedComponent.form.js +13 -0
- package/lib/mjs/components/_classes/nested/NestedComponent.js +10 -8
- package/lib/mjs/components/content/editForm/Content.edit.display.js +8 -0
- package/lib/mjs/components/currency/editForm/Currency.edit.display.js +20 -0
- package/lib/mjs/components/datagrid/DataGrid.js +2 -6
- package/lib/mjs/components/day/editForm/Day.edit.display.js +8 -0
- package/lib/mjs/components/editgrid/EditGrid.d.ts +1 -0
- package/lib/mjs/components/editgrid/EditGrid.js +22 -2
- package/lib/mjs/components/email/editForm/Email.edit.display.js +12 -0
- package/lib/mjs/components/fieldset/editForm/Fieldset.edit.display.js +8 -0
- package/lib/mjs/components/file/editForm/File.edit.file.js +1 -1
- package/lib/mjs/components/form/Form.js +21 -1
- package/lib/mjs/components/hidden/Hidden.d.ts +0 -1
- package/lib/mjs/components/hidden/Hidden.js +1 -1
- package/lib/mjs/components/hidden/editForm/Hidden.edit.display.js +8 -0
- package/lib/mjs/components/html/editForm/HTML.edit.display.js +8 -0
- package/lib/mjs/components/number/Number.d.ts +11 -0
- package/lib/mjs/components/number/Number.js +34 -0
- package/lib/mjs/components/number/editForm/Number.edit.display.js +12 -0
- package/lib/mjs/components/password/editForm/Password.edit.display.js +12 -0
- package/lib/mjs/components/phonenumber/PhoneNumber.form.js +8 -0
- package/lib/mjs/components/select/editForm/Select.edit.data.d.ts +1 -1
- package/lib/mjs/components/select/editForm/Select.edit.data.js +1 -0
- package/lib/mjs/components/tabs/editForm/Tabs.edit.display.js +8 -0
- package/lib/mjs/components/textarea/editForm/TextArea.edit.display.js +12 -0
- package/lib/mjs/components/url/editForm/Url.edit.display.js +12 -0
- package/lib/mjs/components/well/editForm/Well.edit.display.js +8 -0
- package/lib/mjs/package.json +1 -1
- package/lib/mjs/utils/formUtils.d.ts +3 -0
- package/lib/mjs/utils/formUtils.js +2 -2
- package/lib/mjs/utils/index.d.ts +3 -0
- package/lib/mjs/utils/utils.js +6 -18
- package/package.json +2 -2
|
@@ -437,6 +437,39 @@ export default class Component extends Element {
|
|
|
437
437
|
currentRoot = currentRoot.root;
|
|
438
438
|
}
|
|
439
439
|
}
|
|
440
|
+
/**
|
|
441
|
+
* Registers this instance in every root's `childComponentsMap`. Several components can resolve
|
|
442
|
+
* to one data path — see `getSharedPathKey` in `@formio/core` for the rule this follows.
|
|
443
|
+
* @returns {void}
|
|
444
|
+
*/
|
|
445
|
+
registerComponentInstance() {
|
|
446
|
+
const path = this.path;
|
|
447
|
+
if (!path) {
|
|
448
|
+
return;
|
|
449
|
+
}
|
|
450
|
+
// Recorded on every instance, not just the ones that lose the race for the path: it names
|
|
451
|
+
// this registration for `unregisterComponentInstance()`, which can run after `path` changed.
|
|
452
|
+
this.sharedPathKey = FormioUtils.getSharedPathKey(path, this.component.key);
|
|
453
|
+
this.eachRootChildComponentsMap((map) => {
|
|
454
|
+
FormioUtils.registerInstanceAtPath(map, path, this.component.key, this);
|
|
455
|
+
});
|
|
456
|
+
}
|
|
457
|
+
/**
|
|
458
|
+
* Removes this instance from every root's `childComponentsMap`.
|
|
459
|
+
* @param {string} [path] - The path this instance was registered under, when it has since
|
|
460
|
+
* been re-keyed (a DataGrid row index change regenerates paths before unregistering).
|
|
461
|
+
* @returns {void}
|
|
462
|
+
*/
|
|
463
|
+
unregisterComponentInstance(path = this.path) {
|
|
464
|
+
this.eachRootChildComponentsMap((map) => {
|
|
465
|
+
if (map[path] === this) {
|
|
466
|
+
delete map[path];
|
|
467
|
+
}
|
|
468
|
+
if (this.sharedPathKey && map[this.sharedPathKey] === this) {
|
|
469
|
+
delete map[this.sharedPathKey];
|
|
470
|
+
}
|
|
471
|
+
});
|
|
472
|
+
}
|
|
440
473
|
/**
|
|
441
474
|
* Returns if the parent should conditionally clear.
|
|
442
475
|
*
|
|
@@ -2562,19 +2595,6 @@ export default class Component extends Element {
|
|
|
2562
2595
|
return Promise.resolve(editor);
|
|
2563
2596
|
}
|
|
2564
2597
|
else {
|
|
2565
|
-
// Due to an issue with ckeditor not loading styles in the shadowdom (https://github.com/ckeditor/ckeditor5/issues/15824), we need to copy cke-styles to the shadowdom
|
|
2566
|
-
let current = element;
|
|
2567
|
-
while (current) {
|
|
2568
|
-
if (current instanceof ShadowRoot) {
|
|
2569
|
-
const ckeStyles = document.querySelector('style[data-cke="true"]');
|
|
2570
|
-
const clone = document.createElement('style');
|
|
2571
|
-
clone.setAttribute('data-cke', 'true');
|
|
2572
|
-
clone.textContent = ckeStyles.textContent;
|
|
2573
|
-
current.prepend(clone);
|
|
2574
|
-
break;
|
|
2575
|
-
}
|
|
2576
|
-
current = current.parentNode || current.host;
|
|
2577
|
-
}
|
|
2578
2598
|
return ClassicEditor.create(element, settings).then((editor) => {
|
|
2579
2599
|
editor.model.document.on('change', () => onChange(editor.data.get()));
|
|
2580
2600
|
return editor;
|
|
@@ -2601,58 +2621,6 @@ export default class Component extends Element {
|
|
|
2601
2621
|
return Promise.reject();
|
|
2602
2622
|
}
|
|
2603
2623
|
this.quill = new Quill(element, isIEBrowser ? { ...settings, modules: {} } : settings);
|
|
2604
|
-
const root = element.getRootNode();
|
|
2605
|
-
if (root instanceof ShadowRoot && root.getSelection) {
|
|
2606
|
-
const sel = this.quill.selection;
|
|
2607
|
-
// 1. getNativeRange: read selection from shadowRoot instead of document
|
|
2608
|
-
sel.getNativeRange = () => {
|
|
2609
|
-
const shadowSelection = root.getSelection();
|
|
2610
|
-
if (shadowSelection == null || shadowSelection.rangeCount <= 0)
|
|
2611
|
-
return null;
|
|
2612
|
-
const nativeRange = shadowSelection.getRangeAt(0);
|
|
2613
|
-
if (nativeRange == null)
|
|
2614
|
-
return null;
|
|
2615
|
-
return sel.normalizeNative(nativeRange);
|
|
2616
|
-
};
|
|
2617
|
-
// 2. hasFocus: check shadowRoot.activeElement instead of document.activeElement
|
|
2618
|
-
sel.hasFocus = () => {
|
|
2619
|
-
return (root.activeElement === sel.root ||
|
|
2620
|
-
(root.activeElement != null && sel.root.contains(root.activeElement)));
|
|
2621
|
-
};
|
|
2622
|
-
// 3. setNativeRange: use shadowRoot's selection to add/remove ranges
|
|
2623
|
-
const origSetNativeRange = sel.setNativeRange.bind(sel);
|
|
2624
|
-
sel.setNativeRange = (startNode, startOffset, endNode, endOffset, force) => {
|
|
2625
|
-
// Delegate to original logic for the null case (blur)
|
|
2626
|
-
if (startNode == null) {
|
|
2627
|
-
origSetNativeRange(null);
|
|
2628
|
-
return;
|
|
2629
|
-
}
|
|
2630
|
-
if (!sel.hasFocus()) {
|
|
2631
|
-
sel.root.focus({ preventScroll: true });
|
|
2632
|
-
}
|
|
2633
|
-
const shadowSelection = root.getSelection();
|
|
2634
|
-
if (shadowSelection == null)
|
|
2635
|
-
return;
|
|
2636
|
-
const { native } = sel.getNativeRange() || {};
|
|
2637
|
-
endNode = endNode ?? startNode;
|
|
2638
|
-
endOffset = endOffset ?? startOffset;
|
|
2639
|
-
if (native == null ||
|
|
2640
|
-
force ||
|
|
2641
|
-
startNode !== native.startContainer ||
|
|
2642
|
-
startOffset !== native.startOffset ||
|
|
2643
|
-
endNode !== native.endContainer ||
|
|
2644
|
-
endOffset !== native.endOffset) {
|
|
2645
|
-
const range = document.createRange();
|
|
2646
|
-
range.setStart(startNode, startOffset);
|
|
2647
|
-
range.setEnd(endNode, endOffset);
|
|
2648
|
-
shadowSelection.removeAllRanges();
|
|
2649
|
-
shadowSelection.addRange(range);
|
|
2650
|
-
}
|
|
2651
|
-
};
|
|
2652
|
-
document.addEventListener('selectionchange', () => {
|
|
2653
|
-
sel.update();
|
|
2654
|
-
});
|
|
2655
|
-
}
|
|
2656
2624
|
/** This block of code adds the [source] capabilities. See https://codepen.io/anon/pen/ZyEjrQ */
|
|
2657
2625
|
const txtArea = document.createElement('textarea');
|
|
2658
2626
|
txtArea.setAttribute('class', 'quill-source-code');
|
|
@@ -6,6 +6,19 @@ import Components from '../../Components';
|
|
|
6
6
|
*/
|
|
7
7
|
export default function (...extend) {
|
|
8
8
|
return Components.baseEditForm([
|
|
9
|
+
{
|
|
10
|
+
key: 'display',
|
|
11
|
+
components: [
|
|
12
|
+
{
|
|
13
|
+
key: 'labelWidth',
|
|
14
|
+
ignore: true,
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
key: 'labelMargin',
|
|
18
|
+
ignore: true,
|
|
19
|
+
},
|
|
20
|
+
],
|
|
21
|
+
},
|
|
9
22
|
{
|
|
10
23
|
key: 'data',
|
|
11
24
|
ignore: true,
|
|
@@ -553,11 +553,7 @@ export default class NestedComponent extends Field {
|
|
|
553
553
|
components = components || this.components;
|
|
554
554
|
component.destroy(all);
|
|
555
555
|
_.remove(components, { id: component.id });
|
|
556
|
-
component.
|
|
557
|
-
if (map[component.path]) {
|
|
558
|
-
delete map[component.path];
|
|
559
|
-
}
|
|
560
|
-
});
|
|
556
|
+
component.unregisterComponentInstance();
|
|
561
557
|
}
|
|
562
558
|
/**
|
|
563
559
|
* Removes a component provided the API key of that component.
|
|
@@ -666,9 +662,11 @@ export default class NestedComponent extends Field {
|
|
|
666
662
|
validationProcessor({ scope, data, row, instance, paths }, flags) {
|
|
667
663
|
const { dirty } = flags;
|
|
668
664
|
if (this.root && this.root.hasSubWizards && this.page !== this.root.page) {
|
|
669
|
-
instance
|
|
670
|
-
|
|
671
|
-
|
|
665
|
+
// `instance` was resolved by @formio/core against this very map, shared-path rule and
|
|
666
|
+
// all, so only fill in what that lookup cannot reach: components keyed by their data
|
|
667
|
+
// path where core looked under a full path, and components absent from the map.
|
|
668
|
+
instance =
|
|
669
|
+
instance || this.componentsMap?.[paths.dataPath] || this.getComponent(paths.dataPath);
|
|
672
670
|
}
|
|
673
671
|
if (!instance) {
|
|
674
672
|
return;
|
|
@@ -828,6 +826,10 @@ export default class NestedComponent extends Field {
|
|
|
828
826
|
// if no value is provided and noDefault flag, set empty value
|
|
829
827
|
else if (flags.noDefault && component.allowData) {
|
|
830
828
|
flags.resetValue = true;
|
|
829
|
+
// Preserve the live value instead of wiping it, so client-side calculations that read it don't blank out.
|
|
830
|
+
if (component.component.persistent === 'client-only') {
|
|
831
|
+
return false;
|
|
832
|
+
}
|
|
831
833
|
return component.setValue(component.emptyValue, flags);
|
|
832
834
|
}
|
|
833
835
|
else if ((!this.rootPristine || component.visible) &&
|
|
@@ -3,10 +3,30 @@ export default [
|
|
|
3
3
|
key: 'inputMask',
|
|
4
4
|
ignore: true,
|
|
5
5
|
},
|
|
6
|
+
{
|
|
7
|
+
key: 'widget.type',
|
|
8
|
+
ignore: true,
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
key: 'widget',
|
|
12
|
+
ignore: true,
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
key: 'inputMasks',
|
|
16
|
+
ignore: true,
|
|
17
|
+
},
|
|
6
18
|
{
|
|
7
19
|
key: 'allowMultipleMasks',
|
|
8
20
|
ignore: true,
|
|
9
21
|
},
|
|
22
|
+
{
|
|
23
|
+
key: 'labelWidth',
|
|
24
|
+
ignore: true,
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
key: 'labelMargin',
|
|
28
|
+
ignore: true,
|
|
29
|
+
},
|
|
10
30
|
{
|
|
11
31
|
key: 'showWordCount',
|
|
12
32
|
ignore: true,
|
|
@@ -430,12 +430,8 @@ export default class DataGridComponent extends NestedArrayComponent {
|
|
|
430
430
|
component.rowIndex = rowIndex;
|
|
431
431
|
component.row = `${rowIndex}-${colIndex}`;
|
|
432
432
|
entries.forEach(({ instance, oldPath }) => {
|
|
433
|
-
instance.
|
|
434
|
-
|
|
435
|
-
delete map[oldPath];
|
|
436
|
-
}
|
|
437
|
-
map[instance.paths.dataPath] = instance;
|
|
438
|
-
});
|
|
433
|
+
instance.unregisterComponentInstance(oldPath);
|
|
434
|
+
instance.registerComponentInstance();
|
|
439
435
|
});
|
|
440
436
|
});
|
|
441
437
|
}
|
|
@@ -48,6 +48,7 @@ export default class EditGridComponent extends NestedArrayComponent {
|
|
|
48
48
|
setVariableTypeComponents(): void;
|
|
49
49
|
variableTypeComponentsIndexes: any[] | undefined;
|
|
50
50
|
isOpen(editRow: any): boolean;
|
|
51
|
+
shouldBlockUnsavedOpenRows(): boolean;
|
|
51
52
|
isComponentVisibleInSomeRow(component: any): any;
|
|
52
53
|
visibleInHeader: any;
|
|
53
54
|
flattenRowDataValue(dataValue: any): {};
|
|
@@ -310,6 +310,24 @@ export default class EditGridComponent extends NestedArrayComponent {
|
|
|
310
310
|
isOpen(editRow) {
|
|
311
311
|
return [EditRowState.New, EditRowState.Editing, EditRowState.Viewing].includes(editRow.state);
|
|
312
312
|
}
|
|
313
|
+
shouldBlockUnsavedOpenRows() {
|
|
314
|
+
const openRows = this.editRows.filter((editRow) => this.isOpen(editRow));
|
|
315
|
+
if (!openRows.length) {
|
|
316
|
+
return false;
|
|
317
|
+
}
|
|
318
|
+
const isOnlyPristineOpenWhenEmptyRow = this.component.openWhenEmpty &&
|
|
319
|
+
openRows.length === 1 &&
|
|
320
|
+
openRows.every((row) => row.state === EditRowState.New) &&
|
|
321
|
+
openRows.every((row) => {
|
|
322
|
+
let isPristine = true;
|
|
323
|
+
eachComponent(row.components, (comp) => {
|
|
324
|
+
isPristine =
|
|
325
|
+
comp.type === 'form' ? _.isEqual(comp.emptyValue, comp.dataValue) : comp.pristine;
|
|
326
|
+
});
|
|
327
|
+
return isPristine;
|
|
328
|
+
});
|
|
329
|
+
return !isOnlyPristineOpenWhenEmptyRow;
|
|
330
|
+
}
|
|
313
331
|
isComponentVisibleInSomeRow(component) {
|
|
314
332
|
const rows = this.editRows;
|
|
315
333
|
const savedStates = [EditRowState.Saved, EditRowState.Editing, EditRowState.Draft];
|
|
@@ -1070,7 +1088,7 @@ export default class EditGridComponent extends NestedArrayComponent {
|
|
|
1070
1088
|
if (valid === null) {
|
|
1071
1089
|
editRow.errors.push({
|
|
1072
1090
|
type: 'error',
|
|
1073
|
-
message: this.t('componentInvalidRowValidation', { componentKey: this.key })
|
|
1091
|
+
message: this.t('componentInvalidRowValidation', { componentKey: this.key }),
|
|
1074
1092
|
});
|
|
1075
1093
|
}
|
|
1076
1094
|
}
|
|
@@ -1142,7 +1160,9 @@ export default class EditGridComponent extends NestedArrayComponent {
|
|
|
1142
1160
|
}
|
|
1143
1161
|
return false;
|
|
1144
1162
|
}
|
|
1145
|
-
else if (rowsEditing &&
|
|
1163
|
+
else if (rowsEditing &&
|
|
1164
|
+
this.saveEditMode &&
|
|
1165
|
+
(this.shouldBlockUnsavedOpenRows() || this.errors.length)) {
|
|
1146
1166
|
this._errors = this.setCustomValidity(this.t(this.errorMessage('unsavedRowsError')), dirty);
|
|
1147
1167
|
errors.push(...this._errors);
|
|
1148
1168
|
return false;
|
|
@@ -7,6 +7,18 @@ export default [
|
|
|
7
7
|
key: 'allowMultipleMasks',
|
|
8
8
|
ignore: true,
|
|
9
9
|
},
|
|
10
|
+
{
|
|
11
|
+
key: 'inputMasks',
|
|
12
|
+
ignore: true,
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
key: 'widget.type',
|
|
16
|
+
ignore: true,
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
key: 'widget',
|
|
20
|
+
ignore: true,
|
|
21
|
+
},
|
|
10
22
|
{
|
|
11
23
|
key: 'showWordCount',
|
|
12
24
|
ignore: true,
|
|
@@ -290,7 +290,7 @@ export default [
|
|
|
290
290
|
key: 'imageSize',
|
|
291
291
|
label: 'Image Size',
|
|
292
292
|
placeholder: '100',
|
|
293
|
-
tooltip: 'The image size, in square pixels, for previewing images.',
|
|
293
|
+
tooltip: 'The image size, in square pixels, for previewing images. If explicitly set, the frame of the component must be large enough to allow for the specified size.',
|
|
294
294
|
weight: 40,
|
|
295
295
|
clearOnHide: false,
|
|
296
296
|
conditional: {
|
|
@@ -269,7 +269,7 @@ export default class FormComponent extends Component {
|
|
|
269
269
|
return super.attach(element);
|
|
270
270
|
}
|
|
271
271
|
return super.attach(element).then(() => {
|
|
272
|
-
if (this.isSubFormLazyLoad() && !this.
|
|
272
|
+
if (this.isSubFormLazyLoad() && !this.subForm && !this.subFormLoading) {
|
|
273
273
|
this.createSubForm(true);
|
|
274
274
|
}
|
|
275
275
|
if (!this.subFormReady) {
|
|
@@ -366,6 +366,26 @@ export default class FormComponent extends Component {
|
|
|
366
366
|
}
|
|
367
367
|
return super.redraw();
|
|
368
368
|
}
|
|
369
|
+
/**
|
|
370
|
+
* Get Row Index. Declared so the setter below does not shadow the inherited getter.
|
|
371
|
+
* @returns {number} - The row index.
|
|
372
|
+
*/
|
|
373
|
+
get rowIndex() {
|
|
374
|
+
return super.rowIndex;
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* Set Row Index to row and pass it down to the subform so that its components
|
|
378
|
+
* regenerate their paths. Unlike NestedComponent, the subform is not part of
|
|
379
|
+
* this.components, so the row index has to be forwarded explicitly.
|
|
380
|
+
* @param {number} value - The row index.
|
|
381
|
+
* @returns {void}
|
|
382
|
+
*/
|
|
383
|
+
set rowIndex(value) {
|
|
384
|
+
super.rowIndex = value;
|
|
385
|
+
if (this.subForm) {
|
|
386
|
+
this.subForm.rowIndex = value;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
369
389
|
/**
|
|
370
390
|
* Pass everyComponent to subform.
|
|
371
391
|
* @param {any[]} args - Arguments to pass through to the subform's everyComponent method.
|
|
@@ -51,5 +51,16 @@ export default class NumberComponent extends Input {
|
|
|
51
51
|
focus(): void;
|
|
52
52
|
getMaskedValue(value: any): any;
|
|
53
53
|
getValueAsString(value: any, options: any): any;
|
|
54
|
+
setErrorClasses(elements: any, dirty: any, hasErrors: any, hasMessages: any, element?: any): void;
|
|
55
|
+
/**
|
|
56
|
+
* Points the invalid inputs at the rendered error messages through `aria-describedby`, so a
|
|
57
|
+
* screen reader announces what is wrong with the value. The base class only marks the input
|
|
58
|
+
* `aria-invalid`, which says the value was rejected but not why.
|
|
59
|
+
* @param {Array<HTMLElement>} elements - The input elements the errors apply to.
|
|
60
|
+
* @param {boolean} hasErrors - TRUE if the component currently has errors.
|
|
61
|
+
* @returns {void}
|
|
62
|
+
*/
|
|
63
|
+
linkErrorMessages(elements: Array<HTMLElement>, hasErrors: boolean): void;
|
|
64
|
+
errorMessageIds: any[] | undefined;
|
|
54
65
|
}
|
|
55
66
|
import Input from '../_classes/input/Input';
|
|
@@ -268,4 +268,38 @@ export default class NumberComponent extends Input {
|
|
|
268
268
|
element.value = this.getValueAsString(this.formatValue(this.parseValue(element.value)));
|
|
269
269
|
});
|
|
270
270
|
}
|
|
271
|
+
setErrorClasses(elements, dirty, hasErrors, hasMessages, element = this.element) {
|
|
272
|
+
super.setErrorClasses(elements, dirty, hasErrors, hasMessages, element);
|
|
273
|
+
this.linkErrorMessages(elements, hasErrors);
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Points the invalid inputs at the rendered error messages through `aria-describedby`, so a
|
|
277
|
+
* screen reader announces what is wrong with the value. The base class only marks the input
|
|
278
|
+
* `aria-invalid`, which says the value was rejected but not why.
|
|
279
|
+
* @param {Array<HTMLElement>} elements - The input elements the errors apply to.
|
|
280
|
+
* @param {boolean} hasErrors - TRUE if the component currently has errors.
|
|
281
|
+
* @returns {void}
|
|
282
|
+
*/
|
|
283
|
+
linkErrorMessages(elements, hasErrors) {
|
|
284
|
+
const previousIds = this.errorMessageIds || [];
|
|
285
|
+
const renderedMessages = Array.from(this.refs.messageContainer?.children || []);
|
|
286
|
+
const errorIds = hasErrors ? renderedMessages.map((message) => message.id).filter(Boolean) : [];
|
|
287
|
+
const invalidInputs = hasErrors ? Array.from(elements || []) : [];
|
|
288
|
+
const isOwnErrorId = (id) => previousIds.includes(id) || errorIds.includes(id);
|
|
289
|
+
Array.from(this.refs.input || []).forEach((input) => {
|
|
290
|
+
const describedBy = (input.getAttribute('aria-describedby') || '')
|
|
291
|
+
.split(' ')
|
|
292
|
+
.filter((id) => id && !isOwnErrorId(id));
|
|
293
|
+
if (invalidInputs.includes(input)) {
|
|
294
|
+
describedBy.push(...errorIds);
|
|
295
|
+
}
|
|
296
|
+
if (describedBy.length) {
|
|
297
|
+
input.setAttribute('aria-describedby', describedBy.join(' '));
|
|
298
|
+
}
|
|
299
|
+
else {
|
|
300
|
+
input.removeAttribute('aria-describedby');
|
|
301
|
+
}
|
|
302
|
+
});
|
|
303
|
+
this.errorMessageIds = errorIds;
|
|
304
|
+
}
|
|
271
305
|
}
|
|
@@ -11,6 +11,18 @@ export default [
|
|
|
11
11
|
key: 'allowMultipleMasks',
|
|
12
12
|
ignore: true,
|
|
13
13
|
},
|
|
14
|
+
{
|
|
15
|
+
key: 'inputMasks',
|
|
16
|
+
ignore: true,
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
key: 'widget.type',
|
|
20
|
+
ignore: true,
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
key: 'widget',
|
|
24
|
+
ignore: true,
|
|
25
|
+
},
|
|
14
26
|
{
|
|
15
27
|
key: 'showWordCount',
|
|
16
28
|
ignore: true,
|
|
@@ -1057,6 +1057,7 @@ declare const _default: ({
|
|
|
1057
1057
|
alwaysEnabled?: undefined;
|
|
1058
1058
|
} | {
|
|
1059
1059
|
key: string;
|
|
1060
|
+
type: string;
|
|
1060
1061
|
conditional: {
|
|
1061
1062
|
json: {
|
|
1062
1063
|
and: ({
|
|
@@ -1107,7 +1108,6 @@ declare const _default: ({
|
|
|
1107
1108
|
};
|
|
1108
1109
|
};
|
|
1109
1110
|
data?: undefined;
|
|
1110
|
-
type?: undefined;
|
|
1111
1111
|
as?: undefined;
|
|
1112
1112
|
editor?: undefined;
|
|
1113
1113
|
weight?: undefined;
|
|
@@ -9,10 +9,22 @@ export default [
|
|
|
9
9
|
key: 'allowMultipleMasks',
|
|
10
10
|
ignore: true,
|
|
11
11
|
},
|
|
12
|
+
{
|
|
13
|
+
key: 'inputMasks',
|
|
14
|
+
ignore: true,
|
|
15
|
+
},
|
|
12
16
|
{
|
|
13
17
|
key: 'mask',
|
|
14
18
|
ignore: true,
|
|
15
19
|
},
|
|
20
|
+
{
|
|
21
|
+
key: 'widget.type',
|
|
22
|
+
ignore: true,
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
key: 'widget',
|
|
26
|
+
ignore: true,
|
|
27
|
+
},
|
|
16
28
|
{
|
|
17
29
|
type: 'number',
|
|
18
30
|
input: true,
|
|
@@ -7,6 +7,18 @@ export default [
|
|
|
7
7
|
key: 'allowMultipleMasks',
|
|
8
8
|
ignore: true,
|
|
9
9
|
},
|
|
10
|
+
{
|
|
11
|
+
key: 'inputMasks',
|
|
12
|
+
ignore: true,
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
key: 'widget.type',
|
|
16
|
+
ignore: true,
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
key: 'widget',
|
|
20
|
+
ignore: true,
|
|
21
|
+
},
|
|
10
22
|
{
|
|
11
23
|
key: 'showWordCount',
|
|
12
24
|
ignore: true,
|
package/lib/mjs/package.json
CHANGED