@angular/forms 21.2.0-next.2 → 21.2.0-rc.0
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/fesm2022/{_structure-chunk.mjs → _validation_errors-chunk.mjs} +86 -81
- package/fesm2022/_validation_errors-chunk.mjs.map +1 -0
- package/fesm2022/forms.mjs +170 -189
- package/fesm2022/forms.mjs.map +1 -1
- package/fesm2022/signals-compat.mjs +9 -11
- package/fesm2022/signals-compat.mjs.map +1 -1
- package/fesm2022/signals.mjs +1017 -858
- package/fesm2022/signals.mjs.map +1 -1
- package/package.json +4 -4
- package/resources/code-examples.db +0 -0
- package/types/_structure-chunk.d.ts +302 -262
- package/types/forms.d.ts +1 -1
- package/types/signals-compat.d.ts +1 -1
- package/types/signals.d.ts +119 -15
- package/fesm2022/_structure-chunk.mjs.map +0 -1
|
@@ -1,64 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Angular v21.2.0-
|
|
2
|
+
* @license Angular v21.2.0-rc.0
|
|
3
3
|
* (c) 2010-2026 Google LLC. https://angular.dev/
|
|
4
4
|
* License: MIT
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { FormGroup, FormArray, AbstractControl } from '@angular/forms';
|
|
8
7
|
import { untracked, ɵRuntimeError as _RuntimeError, computed, runInInjectionContext, Injector, linkedSignal, signal, APP_ID, effect, inject } from '@angular/core';
|
|
8
|
+
import { AbstractControl, FormGroup, FormArray } from '@angular/forms';
|
|
9
9
|
import { SIGNAL } from '@angular/core/primitives/signals';
|
|
10
10
|
|
|
11
|
-
class CompatValidationError {
|
|
12
|
-
kind = 'compat';
|
|
13
|
-
control;
|
|
14
|
-
fieldTree;
|
|
15
|
-
context;
|
|
16
|
-
message;
|
|
17
|
-
constructor({
|
|
18
|
-
context,
|
|
19
|
-
kind,
|
|
20
|
-
control
|
|
21
|
-
}) {
|
|
22
|
-
this.context = context;
|
|
23
|
-
this.kind = kind;
|
|
24
|
-
this.control = control;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
function signalErrorsToValidationErrors(errors) {
|
|
28
|
-
if (errors.length === 0) {
|
|
29
|
-
return null;
|
|
30
|
-
}
|
|
31
|
-
const errObj = {};
|
|
32
|
-
for (const error of errors) {
|
|
33
|
-
errObj[error.kind] = error instanceof CompatValidationError ? error.context : error;
|
|
34
|
-
}
|
|
35
|
-
return errObj;
|
|
36
|
-
}
|
|
37
|
-
function reactiveErrorsToSignalErrors(errors, control) {
|
|
38
|
-
if (errors === null) {
|
|
39
|
-
return [];
|
|
40
|
-
}
|
|
41
|
-
return Object.entries(errors).map(([kind, context]) => {
|
|
42
|
-
return new CompatValidationError({
|
|
43
|
-
context,
|
|
44
|
-
kind,
|
|
45
|
-
control
|
|
46
|
-
});
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
function extractNestedReactiveErrors(control) {
|
|
50
|
-
const errors = [];
|
|
51
|
-
if (control.errors) {
|
|
52
|
-
errors.push(...reactiveErrorsToSignalErrors(control.errors, control));
|
|
53
|
-
}
|
|
54
|
-
if (control instanceof FormGroup || control instanceof FormArray) {
|
|
55
|
-
for (const c of Object.values(control.controls)) {
|
|
56
|
-
errors.push(...extractNestedReactiveErrors(c));
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
return errors;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
11
|
let boundPathDepth = 0;
|
|
63
12
|
function getBoundPathDepth() {
|
|
64
13
|
return boundPathDepth;
|
|
@@ -679,7 +628,7 @@ class FieldValidationState {
|
|
|
679
628
|
}, ...(ngDevMode ? [{
|
|
680
629
|
debugName: "syncValid"
|
|
681
630
|
}] : []));
|
|
682
|
-
syncTreeErrors = computed(() => this.rawSyncTreeErrors().filter(err => err.fieldTree === this.node.
|
|
631
|
+
syncTreeErrors = computed(() => this.rawSyncTreeErrors().filter(err => err.fieldTree === this.node.fieldTree), ...(ngDevMode ? [{
|
|
683
632
|
debugName: "syncTreeErrors"
|
|
684
633
|
}] : []));
|
|
685
634
|
rawAsyncErrors = computed(() => {
|
|
@@ -694,7 +643,7 @@ class FieldValidationState {
|
|
|
694
643
|
if (this.shouldSkipValidation()) {
|
|
695
644
|
return [];
|
|
696
645
|
}
|
|
697
|
-
return this.rawAsyncErrors().filter(err => err === 'pending' || err.fieldTree === this.node.
|
|
646
|
+
return this.rawAsyncErrors().filter(err => err === 'pending' || err.fieldTree === this.node.fieldTree);
|
|
698
647
|
}, ...(ngDevMode ? [{
|
|
699
648
|
debugName: "asyncErrors"
|
|
700
649
|
}] : []));
|
|
@@ -803,7 +752,7 @@ class FieldNodeContext {
|
|
|
803
752
|
throw new _RuntimeError(1901, ngDevMode && `Cannot resolve path .${targetPathNode.keys.join('.')} relative to field ${['<root>', ...this.node.structure.pathKeys()].join('.')}.`);
|
|
804
753
|
}
|
|
805
754
|
}
|
|
806
|
-
return field.
|
|
755
|
+
return field.fieldTree;
|
|
807
756
|
}, ...(ngDevMode ? [{
|
|
808
757
|
debugName: "resolver"
|
|
809
758
|
}] : []));
|
|
@@ -881,7 +830,7 @@ const FIELD_PROXY_HANDLER = {
|
|
|
881
830
|
const tgt = getTgt();
|
|
882
831
|
const child = tgt.structure.getChild(p);
|
|
883
832
|
if (child !== undefined) {
|
|
884
|
-
return child.
|
|
833
|
+
return child.fieldTree;
|
|
885
834
|
}
|
|
886
835
|
const value = untracked(tgt.value);
|
|
887
836
|
if (isArray(value)) {
|
|
@@ -891,7 +840,7 @@ const FIELD_PROXY_HANDLER = {
|
|
|
891
840
|
if (p === Symbol.iterator) {
|
|
892
841
|
return () => {
|
|
893
842
|
tgt.value();
|
|
894
|
-
return Array.prototype[Symbol.iterator].apply(tgt.
|
|
843
|
+
return Array.prototype[Symbol.iterator].apply(tgt.fieldTree);
|
|
895
844
|
};
|
|
896
845
|
}
|
|
897
846
|
}
|
|
@@ -1272,6 +1221,9 @@ class FieldNode {
|
|
|
1272
1221
|
return undefined;
|
|
1273
1222
|
}
|
|
1274
1223
|
});
|
|
1224
|
+
get fieldTree() {
|
|
1225
|
+
return this.fieldProxy;
|
|
1226
|
+
}
|
|
1275
1227
|
get logicNode() {
|
|
1276
1228
|
return this.structure.logic;
|
|
1277
1229
|
}
|
|
@@ -1626,7 +1578,7 @@ function form(...args) {
|
|
|
1626
1578
|
const adapter = options?.adapter ?? new BasicFieldAdapter();
|
|
1627
1579
|
const fieldRoot = FieldNode.newRoot(fieldManager, model, pathNode, adapter);
|
|
1628
1580
|
fieldManager.createFieldManagementEffect(fieldRoot.structure);
|
|
1629
|
-
return fieldRoot.
|
|
1581
|
+
return fieldRoot.fieldTree;
|
|
1630
1582
|
}
|
|
1631
1583
|
function applyEach(path, schema) {
|
|
1632
1584
|
assertPathIsCurrent(path);
|
|
@@ -1652,19 +1604,21 @@ function applyWhenValue(path, predicate, schema) {
|
|
|
1652
1604
|
}) => predicate(value()), schema);
|
|
1653
1605
|
}
|
|
1654
1606
|
async function submit(form, options) {
|
|
1655
|
-
const node = form
|
|
1656
|
-
const
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
...(options ?? {})
|
|
1607
|
+
const node = untracked(form);
|
|
1608
|
+
const field = options === undefined ? node.structure.root.fieldProxy : form;
|
|
1609
|
+
const detail = {
|
|
1610
|
+
root: node.structure.root.fieldProxy,
|
|
1611
|
+
submitted: form
|
|
1661
1612
|
};
|
|
1662
|
-
|
|
1613
|
+
options = typeof options === 'function' ? {
|
|
1614
|
+
action: options
|
|
1615
|
+
} : options ?? node.structure.fieldManager.submitOptions;
|
|
1616
|
+
const action = options?.action;
|
|
1663
1617
|
if (!action) {
|
|
1664
|
-
throw new _RuntimeError(1915, ngDevMode && 'Cannot submit form with no submit action. Specify the action when creating the form, or as an additional argument to `submit()`.');
|
|
1618
|
+
throw new _RuntimeError(1915, (typeof ngDevMode === 'undefined' || ngDevMode) && 'Cannot submit form with no submit action. Specify the action when creating the form, or as an additional argument to `submit()`.');
|
|
1665
1619
|
}
|
|
1666
|
-
const onInvalid =
|
|
1667
|
-
const ignoreValidators =
|
|
1620
|
+
const onInvalid = options?.onInvalid;
|
|
1621
|
+
const ignoreValidators = options?.ignoreValidators ?? 'pending';
|
|
1668
1622
|
let shouldRunAction = true;
|
|
1669
1623
|
untracked(() => {
|
|
1670
1624
|
markAllAsTouched(node);
|
|
@@ -1677,24 +1631,36 @@ async function submit(form, options) {
|
|
|
1677
1631
|
try {
|
|
1678
1632
|
if (shouldRunAction) {
|
|
1679
1633
|
node.submitState.selfSubmitting.set(true);
|
|
1680
|
-
const errors = await untracked(() => action?.(
|
|
1634
|
+
const errors = await untracked(() => action?.(field, detail));
|
|
1681
1635
|
errors && setSubmissionErrors(node, errors);
|
|
1682
1636
|
return !errors || isArray(errors) && errors.length === 0;
|
|
1683
1637
|
} else {
|
|
1684
|
-
untracked(() => onInvalid?.(
|
|
1638
|
+
untracked(() => onInvalid?.(field, detail));
|
|
1685
1639
|
}
|
|
1686
1640
|
return false;
|
|
1687
1641
|
} finally {
|
|
1688
1642
|
node.submitState.selfSubmitting.set(false);
|
|
1689
1643
|
}
|
|
1690
1644
|
}
|
|
1645
|
+
function schema(fn) {
|
|
1646
|
+
return SchemaImpl.create(fn);
|
|
1647
|
+
}
|
|
1648
|
+
function markAllAsTouched(node) {
|
|
1649
|
+
if (node.validationState.shouldSkipValidation()) {
|
|
1650
|
+
return;
|
|
1651
|
+
}
|
|
1652
|
+
node.markAsTouched();
|
|
1653
|
+
for (const child of node.structure.children()) {
|
|
1654
|
+
markAllAsTouched(child);
|
|
1655
|
+
}
|
|
1656
|
+
}
|
|
1691
1657
|
function setSubmissionErrors(submittedField, errors) {
|
|
1692
1658
|
if (!isArray(errors)) {
|
|
1693
1659
|
errors = [errors];
|
|
1694
1660
|
}
|
|
1695
1661
|
const errorsByField = new Map();
|
|
1696
1662
|
for (const error of errors) {
|
|
1697
|
-
const errorWithField = addDefaultField(error, submittedField.
|
|
1663
|
+
const errorWithField = addDefaultField(error, submittedField.fieldTree);
|
|
1698
1664
|
const field = errorWithField.fieldTree();
|
|
1699
1665
|
let fieldErrors = errorsByField.get(field);
|
|
1700
1666
|
if (!fieldErrors) {
|
|
@@ -1707,18 +1673,57 @@ function setSubmissionErrors(submittedField, errors) {
|
|
|
1707
1673
|
field.submitState.submissionErrors.set(fieldErrors);
|
|
1708
1674
|
}
|
|
1709
1675
|
}
|
|
1710
|
-
|
|
1711
|
-
|
|
1676
|
+
|
|
1677
|
+
class CompatValidationError {
|
|
1678
|
+
kind = 'compat';
|
|
1679
|
+
control;
|
|
1680
|
+
fieldTree;
|
|
1681
|
+
context;
|
|
1682
|
+
message;
|
|
1683
|
+
constructor({
|
|
1684
|
+
context,
|
|
1685
|
+
kind,
|
|
1686
|
+
control
|
|
1687
|
+
}) {
|
|
1688
|
+
this.context = context;
|
|
1689
|
+
this.kind = kind;
|
|
1690
|
+
this.control = control;
|
|
1691
|
+
}
|
|
1712
1692
|
}
|
|
1713
|
-
function
|
|
1714
|
-
if (
|
|
1715
|
-
return;
|
|
1693
|
+
function signalErrorsToValidationErrors(errors) {
|
|
1694
|
+
if (errors.length === 0) {
|
|
1695
|
+
return null;
|
|
1716
1696
|
}
|
|
1717
|
-
|
|
1718
|
-
for (const
|
|
1719
|
-
|
|
1697
|
+
const errObj = {};
|
|
1698
|
+
for (const error of errors) {
|
|
1699
|
+
errObj[error.kind] = error instanceof CompatValidationError ? error.context : error;
|
|
1700
|
+
}
|
|
1701
|
+
return errObj;
|
|
1702
|
+
}
|
|
1703
|
+
function reactiveErrorsToSignalErrors(errors, control) {
|
|
1704
|
+
if (errors === null) {
|
|
1705
|
+
return [];
|
|
1706
|
+
}
|
|
1707
|
+
return Object.entries(errors).map(([kind, context]) => {
|
|
1708
|
+
return new CompatValidationError({
|
|
1709
|
+
context,
|
|
1710
|
+
kind,
|
|
1711
|
+
control
|
|
1712
|
+
});
|
|
1713
|
+
});
|
|
1714
|
+
}
|
|
1715
|
+
function extractNestedReactiveErrors(control) {
|
|
1716
|
+
const errors = [];
|
|
1717
|
+
if (control.errors) {
|
|
1718
|
+
errors.push(...reactiveErrorsToSignalErrors(control.errors, control));
|
|
1720
1719
|
}
|
|
1720
|
+
if (control instanceof FormGroup || control instanceof FormArray) {
|
|
1721
|
+
for (const c of Object.values(control.controls)) {
|
|
1722
|
+
errors.push(...extractNestedReactiveErrors(c));
|
|
1723
|
+
}
|
|
1724
|
+
}
|
|
1725
|
+
return errors;
|
|
1721
1726
|
}
|
|
1722
1727
|
|
|
1723
1728
|
export { BasicFieldAdapter, CompatValidationError, DEBOUNCER, FieldNode, FieldNodeState, FieldNodeStructure, FieldPathNode, MAX, MAX_LENGTH, MIN, MIN_LENGTH, MetadataKey, MetadataReducer, PATTERN, REQUIRED, addDefaultField, apply, applyEach, applyWhen, applyWhenValue, assertPathIsCurrent, calculateValidationSelfStatus, createManagedMetadataKey, createMetadataKey, extractNestedReactiveErrors, form, getInjectorFromOptions, metadata, normalizeFormArgs, schema, signalErrorsToValidationErrors, submit };
|
|
1724
|
-
//# sourceMappingURL=
|
|
1729
|
+
//# sourceMappingURL=_validation_errors-chunk.mjs.map
|