@angular/forms 22.0.0-next.4 → 22.0.0-next.6

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.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Angular v22.0.0-next.4
2
+ * @license Angular v22.0.0-next.6
3
3
  * (c) 2010-2026 Google LLC. https://angular.dev/
4
4
  * License: MIT
5
5
  */
@@ -58,6 +58,9 @@ class AbstractLogic {
58
58
  const fns = this.predicates ? other.fns.map(fn => wrapWithPredicates(this.predicates, fn)) : other.fns;
59
59
  this.fns.push(...fns);
60
60
  }
61
+ hasRules() {
62
+ return this.fns.length > 0;
63
+ }
61
64
  }
62
65
  class BooleanOrLogic extends AbstractLogic {
63
66
  get defaultValue() {
@@ -162,9 +165,15 @@ class LogicContainer {
162
165
  this.syncTreeErrors = ArrayMergeIgnoreLogic.ignoreNull(predicates);
163
166
  this.asyncErrors = ArrayMergeIgnoreLogic.ignoreNull(predicates);
164
167
  }
168
+ hasAnyLogic() {
169
+ return this.hidden.hasRules() || this.disabledReasons.hasRules() || this.readonly.hasRules() || this.syncErrors.hasRules() || this.syncTreeErrors.hasRules() || this.asyncErrors.hasRules() || this.metadata.size > 0;
170
+ }
165
171
  hasMetadata(key) {
166
172
  return this.metadata.has(key);
167
173
  }
174
+ hasMetadataKeys() {
175
+ return this.metadata.size > 0;
176
+ }
168
177
  getMetadataKeys() {
169
178
  return this.metadata.keys();
170
179
  }
@@ -241,6 +250,14 @@ class LogicNodeBuilder extends AbstractLogicNodeBuilder {
241
250
  builder: subBuilder
242
251
  }) => subBuilder.hasLogic(builder));
243
252
  }
253
+ hasRules() {
254
+ return this.all.length > 0;
255
+ }
256
+ anyChildHasLogic() {
257
+ return this.all.some(({
258
+ builder
259
+ }) => builder.anyChildHasLogic());
260
+ }
244
261
  mergeIn(other, predicate) {
245
262
  if (predicate) {
246
263
  this.all.push({
@@ -306,6 +323,17 @@ class NonMergeableLogicNodeBuilder extends AbstractLogicNodeBuilder {
306
323
  hasLogic(builder) {
307
324
  return this === builder;
308
325
  }
326
+ hasRules() {
327
+ return this.logic.hasAnyLogic() || this.children.size > 0;
328
+ }
329
+ anyChildHasLogic() {
330
+ for (const child of this.children.values()) {
331
+ if (child.hasRules()) {
332
+ return true;
333
+ }
334
+ }
335
+ return false;
336
+ }
309
337
  }
310
338
  class LeafLogicNode {
311
339
  builder;
@@ -337,7 +365,16 @@ class LeafLogicNode {
337
365
  }
338
366
  }
339
367
  hasLogic(builder) {
340
- return this.builder?.hasLogic(builder) ?? false;
368
+ if (!this.builder) {
369
+ return false;
370
+ }
371
+ return this.builder.hasLogic(builder);
372
+ }
373
+ hasRules() {
374
+ return this.builder ? this.builder.hasRules() : false;
375
+ }
376
+ anyChildHasLogic() {
377
+ return this.builder ? this.builder.anyChildHasLogic() : false;
341
378
  }
342
379
  }
343
380
  class CompositeLogicNode {
@@ -356,6 +393,12 @@ class CompositeLogicNode {
356
393
  hasLogic(builder) {
357
394
  return this.all.some(node => node.hasLogic(builder));
358
395
  }
396
+ hasRules() {
397
+ return this.all.some(node => node.hasRules());
398
+ }
399
+ anyChildHasLogic() {
400
+ return this.all.some(child => child.anyChildHasLogic());
401
+ }
359
402
  }
360
403
  function getAllChildBuilders(builder, key) {
361
404
  if (builder instanceof LogicNodeBuilder) {
@@ -568,10 +611,12 @@ function override(getInitial) {
568
611
  getInitial: () => getInitial?.()
569
612
  };
570
613
  }
614
+ const IS_ASYNC_VALIDATION_RESOURCE = Symbol('IS_ASYNC_VALIDATION_RESOURCE');
571
615
  class MetadataKey {
572
616
  reducer;
573
617
  create;
574
618
  brand;
619
+ [IS_ASYNC_VALIDATION_RESOURCE];
575
620
  constructor(reducer, create) {
576
621
  this.reducer = reducer;
577
622
  this.create = create;
@@ -806,13 +851,20 @@ class FieldMetadataState {
806
851
  metadata = new Map();
807
852
  constructor(node) {
808
853
  this.node = node;
809
- for (const key of this.node.logicNode.logic.getMetadataKeys()) {
810
- if (key.create) {
811
- const logic = this.node.logicNode.logic.getMetadata(key);
812
- const result = untracked(() => runInInjectionContext(this.node.structure.injector, () => key.create(computed(() => logic.compute(this.node.context)))));
813
- this.metadata.set(key, result);
814
- }
854
+ }
855
+ runMetadataCreateLifecycle() {
856
+ if (!this.node.logicNode.logic.hasMetadataKeys()) {
857
+ return;
815
858
  }
859
+ untracked(() => runInInjectionContext(this.node.structure.injector, () => {
860
+ for (const key of this.node.logicNode.logic.getMetadataKeys()) {
861
+ if (key.create) {
862
+ const logic = this.node.logicNode.logic.getMetadata(key);
863
+ const result = key.create(this.node, computed(() => logic.compute(this.node.context)));
864
+ this.metadata.set(key, result);
865
+ }
866
+ }
867
+ }));
816
868
  }
817
869
  get(key) {
818
870
  if (this.has(key)) {
@@ -906,6 +958,7 @@ class FieldNodeStructure {
906
958
  createChildNode;
907
959
  identitySymbol = Symbol();
908
960
  _injector = undefined;
961
+ _anyChildHasLogic;
909
962
  get injector() {
910
963
  this._injector ??= Injector.create({
911
964
  providers: [],
@@ -919,13 +972,26 @@ class FieldNodeStructure {
919
972
  this.createChildNode = createChildNode;
920
973
  }
921
974
  children() {
975
+ this.ensureChildrenMap();
922
976
  const map = this.childrenMap();
923
977
  if (map === undefined) {
924
978
  return [];
925
979
  }
926
980
  return Array.from(map.byPropertyKey.values()).map(child => untracked(child.reader));
927
981
  }
982
+ _areChildrenMaterialized() {
983
+ return untracked(this.childrenMap) !== undefined;
984
+ }
985
+ ensureChildrenMap() {
986
+ if (this._areChildrenMaterialized()) {
987
+ return;
988
+ }
989
+ untracked(() => {
990
+ this.childrenMap.update(current => this.computeChildrenMap(this.value(), current, true));
991
+ });
992
+ }
928
993
  getChild(key) {
994
+ this.ensureChildrenMap();
929
995
  const strKey = key.toString();
930
996
  let reader = untracked(this.childrenMap)?.byPropertyKey.get(strKey)?.reader;
931
997
  if (!reader) {
@@ -986,67 +1052,73 @@ class FieldNodeStructure {
986
1052
  createChildrenMap() {
987
1053
  return linkedSignal({
988
1054
  source: this.value,
989
- computation: (value, previous) => {
990
- if (!isObject(value)) {
991
- return undefined;
992
- }
993
- const prevData = previous?.value ?? {
994
- byPropertyKey: new Map()
995
- };
996
- let data;
997
- const parentIsArray = isArray(value);
998
- if (prevData !== undefined) {
999
- if (parentIsArray) {
1000
- data = maybeRemoveStaleArrayFields(prevData, value, this.identitySymbol);
1001
- } else {
1002
- data = maybeRemoveStaleObjectFields(prevData, value);
1003
- }
1055
+ computation: (value, previous) => this.computeChildrenMap(value, previous?.value, false)
1056
+ });
1057
+ }
1058
+ computeChildrenMap(value, prevData, forceMaterialize) {
1059
+ if (!isObject(value)) {
1060
+ return undefined;
1061
+ }
1062
+ if (!forceMaterialize && prevData === undefined) {
1063
+ if (!(this._anyChildHasLogic ??= this.logic.anyChildHasLogic())) {
1064
+ return undefined;
1065
+ }
1066
+ }
1067
+ prevData ??= {
1068
+ byPropertyKey: new Map()
1069
+ };
1070
+ let materializedChildren;
1071
+ const parentIsArray = isArray(value);
1072
+ if (prevData !== undefined) {
1073
+ if (parentIsArray) {
1074
+ materializedChildren = maybeRemoveStaleArrayFields(prevData, value, this.identitySymbol);
1075
+ } else {
1076
+ materializedChildren = maybeRemoveStaleObjectFields(prevData, value);
1077
+ }
1078
+ }
1079
+ for (const key of Object.keys(value)) {
1080
+ let trackingKey = undefined;
1081
+ const childValue = value[key];
1082
+ if (childValue === undefined) {
1083
+ if (prevData.byPropertyKey.has(key)) {
1084
+ materializedChildren ??= {
1085
+ ...prevData
1086
+ };
1087
+ materializedChildren.byPropertyKey.delete(key);
1004
1088
  }
1005
- for (const key of Object.keys(value)) {
1006
- let trackingKey = undefined;
1007
- const childValue = value[key];
1008
- if (childValue === undefined) {
1009
- if (prevData.byPropertyKey.has(key)) {
1010
- data ??= {
1011
- ...prevData
1012
- };
1013
- data.byPropertyKey.delete(key);
1014
- }
1015
- continue;
1016
- }
1017
- if (parentIsArray && isObject(childValue) && !isArray(childValue)) {
1018
- trackingKey = childValue[this.identitySymbol] ??= Symbol(ngDevMode ? `id:${globalId++}` : '');
1019
- }
1020
- let childNode;
1021
- if (trackingKey) {
1022
- if (!prevData.byTrackingKey?.has(trackingKey)) {
1023
- data ??= {
1024
- ...prevData
1025
- };
1026
- data.byTrackingKey ??= new Map();
1027
- data.byTrackingKey.set(trackingKey, this.createChildNode(key, trackingKey, parentIsArray));
1028
- }
1029
- childNode = (data ?? prevData).byTrackingKey.get(trackingKey);
1030
- }
1031
- const child = prevData.byPropertyKey.get(key);
1032
- if (child === undefined) {
1033
- data ??= {
1034
- ...prevData
1035
- };
1036
- data.byPropertyKey.set(key, {
1037
- reader: this.createReader(key),
1038
- node: childNode ?? this.createChildNode(key, trackingKey, parentIsArray)
1039
- });
1040
- } else if (childNode && childNode !== child.node) {
1041
- data ??= {
1042
- ...prevData
1043
- };
1044
- child.node = childNode;
1045
- }
1089
+ continue;
1090
+ }
1091
+ if (parentIsArray && isObject(childValue) && !isArray(childValue)) {
1092
+ trackingKey = childValue[this.identitySymbol] ??= Symbol(ngDevMode ? `id:${globalId++}` : '');
1093
+ }
1094
+ let childNode;
1095
+ if (trackingKey) {
1096
+ if (!prevData.byTrackingKey?.has(trackingKey)) {
1097
+ materializedChildren ??= {
1098
+ ...prevData
1099
+ };
1100
+ materializedChildren.byTrackingKey ??= new Map();
1101
+ materializedChildren.byTrackingKey.set(trackingKey, this.createChildNode(key, trackingKey, parentIsArray));
1046
1102
  }
1047
- return data ?? prevData;
1103
+ childNode = (materializedChildren ?? prevData).byTrackingKey.get(trackingKey);
1048
1104
  }
1049
- });
1105
+ const child = prevData.byPropertyKey.get(key);
1106
+ if (child === undefined) {
1107
+ materializedChildren ??= {
1108
+ ...prevData
1109
+ };
1110
+ materializedChildren.byPropertyKey.set(key, {
1111
+ reader: this.createReader(key),
1112
+ node: childNode ?? this.createChildNode(key, trackingKey, parentIsArray)
1113
+ });
1114
+ } else if (childNode && childNode !== child.node) {
1115
+ materializedChildren ??= {
1116
+ ...prevData
1117
+ };
1118
+ child.node = childNode;
1119
+ }
1120
+ }
1121
+ return materializedChildren ?? prevData;
1050
1122
  }
1051
1123
  createReader(key) {
1052
1124
  return computed(() => this.childrenMap()?.byPropertyKey.get(key)?.node);
@@ -1208,6 +1280,7 @@ class FieldNode {
1208
1280
  this.metadataState = new FieldMetadataState(this);
1209
1281
  this.submitState = new FieldSubmitState(this);
1210
1282
  this.controlValue = this.controlValueSignal();
1283
+ this.metadataState.runMetadataCreateLifecycle();
1211
1284
  }
1212
1285
  focusBoundControl(options) {
1213
1286
  this.getBindingForFocus()?.focus(options);
@@ -1305,6 +1378,9 @@ class FieldNode {
1305
1378
  metadata(key) {
1306
1379
  return this.metadataState.get(key);
1307
1380
  }
1381
+ getError(kind) {
1382
+ return this.errors().find(e => e.kind === kind);
1383
+ }
1308
1384
  hasMetadata(key) {
1309
1385
  return this.metadataState.has(key);
1310
1386
  }
@@ -1348,6 +1424,21 @@ class FieldNode {
1348
1424
  child._reset();
1349
1425
  }
1350
1426
  }
1427
+ reloadValidation() {
1428
+ untracked(() => this._reloadValidation());
1429
+ }
1430
+ _reloadValidation() {
1431
+ const keys = this.logicNode.logic.getMetadataKeys();
1432
+ for (const key of keys) {
1433
+ if (key[IS_ASYNC_VALIDATION_RESOURCE]) {
1434
+ const resource = this.metadata(key);
1435
+ resource.reload?.();
1436
+ }
1437
+ }
1438
+ for (const child of this.structure.children()) {
1439
+ child._reloadValidation();
1440
+ }
1441
+ }
1351
1442
  controlValueSignal() {
1352
1443
  const controlValue = linkedSignal(this.value, ...(ngDevMode ? [{
1353
1444
  debugName: "controlValue"
@@ -1736,5 +1827,5 @@ function extractNestedReactiveErrors(control) {
1736
1827
  return errors;
1737
1828
  }
1738
1829
 
1739
- 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, isArray, isObject, metadata, normalizeFormArgs, schema, signalErrorsToValidationErrors, submit };
1830
+ export { BasicFieldAdapter, CompatValidationError, DEBOUNCER, FieldNode, FieldNodeState, FieldNodeStructure, FieldPathNode, IS_ASYNC_VALIDATION_RESOURCE, MAX, MAX_LENGTH, MIN, MIN_LENGTH, MetadataKey, MetadataReducer, PATTERN, REQUIRED, addDefaultField, apply, applyEach, applyWhen, applyWhenValue, assertPathIsCurrent, calculateValidationSelfStatus, createManagedMetadataKey, createMetadataKey, extractNestedReactiveErrors, form, getInjectorFromOptions, isArray, isObject, metadata, normalizeFormArgs, schema, signalErrorsToValidationErrors, submit };
1740
1831
  //# sourceMappingURL=_validation_errors-chunk.mjs.map