@angular/forms 21.0.4 → 21.1.0-next.1

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,11 +1,11 @@
1
1
  /**
2
- * @license Angular v21.0.4
2
+ * @license Angular v21.1.0-next.1
3
3
  * (c) 2010-2025 Google LLC. https://angular.dev/
4
4
  * License: MIT
5
5
  */
6
6
 
7
7
  import * as i0 from '@angular/core';
8
- import { InjectionToken, ɵControl as _Control, Injector, ɵCONTROL as _CONTROL, ɵɵcontrolCreate as __controlCreate, ɵcontrolUpdate as _controlUpdate, Signal, ɵFieldState as _FieldState, Provider, WritableSignal, DestroyableInjector } from '@angular/core';
8
+ import { InjectionToken, ɵControl as _Control, ɵCONTROL as _CONTROL, ɵɵcontrolCreate as __controlCreate, ɵcontrolUpdate as _controlUpdate, ɵInteropControl as _InteropControl, ɵFieldState as _FieldState, Signal, Provider, WritableSignal, DestroyableInjector, Injector } from '@angular/core';
9
9
  import * as _angular_forms from '@angular/forms';
10
10
  import { NgControl, AbstractControl, ValidationErrors, FormControlStatus, ControlValueAccessor, ValidatorFn } from '@angular/forms';
11
11
  import { StandardSchemaV1 } from '@standard-schema/spec';
@@ -69,1043 +69,1006 @@ declare const FIELD: InjectionToken<Field<unknown>>;
69
69
  * @experimental 21.0.0
70
70
  */
71
71
  declare class Field<T> implements _Control<T> {
72
- readonly element: HTMLElement;
73
- readonly injector: Injector;
72
+ private readonly injector;
73
+ private config;
74
+ readonly classes: (readonly [string, i0.Signal<boolean>])[];
74
75
  readonly field: i0.InputSignal<FieldTree<T>>;
75
76
  readonly state: i0.Signal<[T] extends [_angular_forms.AbstractControl<any, any, any>] ? CompatFieldState<T, string | number> : FieldState<T, string | number>>;
76
77
  readonly [_CONTROL]: {
77
78
  readonly create: typeof __controlCreate;
78
79
  readonly update: typeof _controlUpdate;
79
80
  };
80
- private config;
81
81
  /** Any `ControlValueAccessor` instances provided on the host element. */
82
82
  private readonly controlValueAccessors;
83
83
  /** A lazily instantiated fake `NgControl`. */
84
84
  private interopNgControl;
85
+ /** A `ControlValueAccessor`, if configured, for the host component. */
86
+ get ɵinteropControl(): _InteropControl | undefined;
85
87
  /** Lazily instantiates a fake `NgControl` for this field. */
86
88
  protected getOrCreateNgControl(): InteropNgControl;
89
+ ɵregister(): void;
87
90
  static ɵfac: i0.ɵɵFactoryDeclaration<Field<any>, never>;
88
91
  static ɵdir: i0.ɵɵDirectiveDeclaration<Field<any>, "[field]", never, { "field": { "alias": "field"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
89
92
  }
90
93
 
91
94
  /**
92
- * Sets a value for the {@link MetadataKey} for this field.
93
- *
94
- * This value is combined via a reduce operation defined by the particular key,
95
- * since multiple rules in the schema might set values for it.
96
- *
97
- * @param path The target path to set the metadata for.
98
- * @param key The metadata key
99
- * @param logic A function that receives the `FieldContext` and returns a value for the metadata.
100
- * @template TValue The type of value stored in the field the logic is bound to.
101
- * @template TKey The type of metadata key.
102
- * @template TPathKind The kind of path the logic is bound to (a root path, child path, or item of an array)
95
+ * Represents metadata that may be defined on a field when it is created using a `metadata` rule
96
+ * in the schema. A particular `MetadataKey` can only be defined on a particular field **once**.
103
97
  *
104
98
  * @category logic
105
99
  * @experimental 21.0.0
106
100
  */
107
- declare function metadata<TValue, TKey extends MetadataKey<any, any, any>, TPathKind extends PathKind = PathKind.Root>(path: SchemaPath<TValue, SchemaPathRules.Supported, TPathKind>, key: TKey, logic: NoInfer<LogicFn<TValue, MetadataSetterType<TKey>, TPathKind>>): TKey;
101
+ declare class MetadataKey<TValue> {
102
+ private brand;
103
+ /** Use {@link createMetadataKey}. */
104
+ private constructor();
105
+ }
108
106
  /**
109
- * A reducer that determines the accumulated value for a metadata key by reducing the individual
110
- * values contributed from `metadata()` rules.
107
+ * Creates a {@link MetadataKey}.
111
108
  *
112
- * @template TAcc The accumulated type of the reduce operation.
113
- * @template TItem The type of the individual items that are reduced over.
114
- * @experimental 21.0.2
109
+ * @experimental 21.0.0
115
110
  */
116
- interface MetadataReducer<TAcc, TItem> {
117
- /** The reduce function. */
118
- reduce: (acc: TAcc, item: TItem) => TAcc;
119
- /** Gets the initial accumulated value. */
120
- getInitial: () => TAcc;
121
- }
122
- declare const MetadataReducer: {
123
- /** Creates a reducer that accumulates a list of its individual item values. */
124
- readonly list: <TItem>() => MetadataReducer<TItem[], TItem | undefined>;
125
- /** Creates a reducer that accumulates the min of its individual item values. */
126
- readonly min: () => MetadataReducer<number | undefined, number | undefined>;
127
- /** Creates a reducer that accumulates a the max of its individual item values. */
128
- readonly max: () => MetadataReducer<number | undefined, number | undefined>;
129
- /** Creates a reducer that logically or's its accumulated value with each individual item value. */
130
- readonly or: () => MetadataReducer<boolean, boolean>;
131
- /** Creates a reducer that logically and's its accumulated value with each individual item value. */
132
- readonly and: () => MetadataReducer<boolean, boolean>;
133
- /** Creates a reducer that always takes the next individual item value as the accumulated value. */
134
- readonly override: typeof override;
135
- };
136
- declare function override<T>(): MetadataReducer<T | undefined, T>;
137
- declare function override<T>(getInitial: () => T): MetadataReducer<T, T>;
111
+ declare function createMetadataKey<TValue>(): MetadataKey<TValue>;
138
112
  /**
139
113
  * Represents metadata that is aggregated from multiple parts according to the key's reducer
140
114
  * function. A value can be contributed to the aggregated value for a field using an
141
- * `metadata` rule in the schema. There may be multiple rules in a schema that contribute
142
- * values to the same `MetadataKey` of the same field.
143
- *
144
- * @template TRead The type read from the `FieldState` for this key
145
- * @template TWrite The type written to this key using the `metadata()` rule
146
- * @template TAcc The type of the reducer's accumulated value.
115
+ * `aggregateMetadata` rule in the schema. There may be multiple rules in a schema that contribute
116
+ * values to the same `AggregateMetadataKey` of the same field.
147
117
  *
148
118
  * @experimental 21.0.0
149
119
  */
150
- declare class MetadataKey<TRead, TWrite, TAcc> {
151
- readonly reducer: MetadataReducer<TAcc, TWrite>;
152
- readonly create: ((s: Signal<TAcc>) => TRead) | undefined;
120
+ declare class AggregateMetadataKey<TAcc, TItem> {
121
+ readonly reduce: (acc: TAcc, item: TItem) => TAcc;
122
+ readonly getInitial: () => TAcc;
153
123
  private brand;
154
124
  /** Use {@link reducedMetadataKey}. */
155
- protected constructor(reducer: MetadataReducer<TAcc, TWrite>, create: ((s: Signal<TAcc>) => TRead) | undefined);
125
+ private constructor();
156
126
  }
157
127
  /**
158
- * Extracts the the type that can be set into the given metadata key type using the `metadata()` rule.
159
- *
160
- * @template TKey The `MetadataKey` type
128
+ * Creates an {@link AggregateMetadataKey} that reduces its individual values into an accumulated
129
+ * value using the given `reduce` and `getInitial` functions.
130
+ * @param reduce The reducer function.
131
+ * @param getInitial A function that gets the initial value for the reduce operation.
161
132
  *
162
133
  * @experimental 21.0.0
163
134
  */
164
- type MetadataSetterType<TKey> = TKey extends MetadataKey<any, infer TWrite, any> ? TWrite : never;
135
+ declare function reducedMetadataKey<TAcc, TItem>(reduce: (acc: TAcc, item: TItem) => TAcc, getInitial: NoInfer<() => TAcc>): AggregateMetadataKey<TAcc, TItem>;
165
136
  /**
166
- * Creates a metadata key used to contain a computed value.
167
- * The last value set on a given field tree node overrides any previously set values.
168
- *
169
- * @template TWrite The type written to this key using the `metadata()` rule
137
+ * Creates an {@link AggregateMetadataKey} that reduces its individual values into a list.
170
138
  *
171
139
  * @experimental 21.0.0
172
140
  */
173
- declare function createMetadataKey<TWrite>(): MetadataKey<Signal<TWrite | undefined>, TWrite, TWrite | undefined>;
141
+ declare function listMetadataKey<TItem>(): AggregateMetadataKey<TItem[], TItem | undefined>;
174
142
  /**
175
- * Creates a metadata key used to contain a computed value.
176
- *
177
- * @param reducer The reducer used to combine individually set values into the final computed value.
178
- * @template TWrite The type written to this key using the `metadata()` rule
179
- * @template TAcc The type of the reducer's accumulated value.
143
+ * Creates {@link AggregateMetadataKey} that reduces its individual values by taking their min.
180
144
  *
181
145
  * @experimental 21.0.0
182
146
  */
183
- declare function createMetadataKey<TWrite, TAcc>(reducer: MetadataReducer<TAcc, TWrite>): MetadataKey<Signal<TAcc>, TWrite, TAcc>;
147
+ declare function minMetadataKey(): AggregateMetadataKey<number | undefined, number | undefined>;
184
148
  /**
185
- * Creates a metadata key that exposes a managed value based on the accumulated result of the values
186
- * written to the key. The accumulated value takes the last value set on a given field tree node,
187
- * overriding any previously set values.
188
- *
189
- * @param create A function that receives a signal of the accumulated value and returns the managed
190
- * value based on it. This function runs during the construction of the `FieldTree` node,
191
- * and runs in the injection context of that node.
192
- * @template TRead The type read from the `FieldState` for this key
193
- * @template TWrite The type written to this key using the `metadata()` rule
149
+ * Creates {@link AggregateMetadataKey} that reduces its individual values by taking their max.
194
150
  *
195
151
  * @experimental 21.0.0
196
152
  */
197
- declare function createManagedMetadataKey<TRead, TWrite>(create: (s: Signal<TWrite | undefined>) => TRead): MetadataKey<TRead, TWrite, TWrite | undefined>;
153
+ declare function maxMetadataKey(): AggregateMetadataKey<number | undefined, number | undefined>;
198
154
  /**
199
- * Creates a metadata key that exposes a managed value based on the accumulated result of the values
200
- * written to the key.
155
+ * Creates an {@link AggregateMetadataKey} that reduces its individual values by logically or-ing
156
+ * them.
201
157
  *
202
- * @param create A function that receives a signal of the accumulated value and returns the managed
203
- * value based on it. This function runs during the construction of the `FieldTree` node,
204
- * and runs in the injection context of that node.
205
- * @param reducer The reducer used to combine individual value written to the key,
206
- * this will determine the accumulated value that the create function receives.
207
- * @template TRead The type read from the `FieldState` for this key
208
- * @template TWrite The type written to this key using the `metadata()` rule
209
- * @template TAcc The type of the reducer's accumulated value.
158
+ * @experimental 21.0.0
159
+ */
160
+ declare function orMetadataKey(): AggregateMetadataKey<boolean, boolean>;
161
+ /**
162
+ * Creates an {@link AggregateMetadataKey} that reduces its individual values by logically and-ing
163
+ * them.
210
164
  *
211
165
  * @experimental 21.0.0
212
166
  */
213
- declare function createManagedMetadataKey<TRead, TWrite, TAcc>(create: (s: Signal<TAcc>) => TRead, reducer: MetadataReducer<TAcc, TWrite>): MetadataKey<TRead, TWrite, TAcc>;
167
+ declare function andMetadataKey(): AggregateMetadataKey<boolean, boolean>;
214
168
  /**
215
- * A {@link MetadataKey} representing whether the field is required.
169
+ * An {@link AggregateMetadataKey} representing whether the field is required.
216
170
  *
217
171
  * @category validation
218
172
  * @experimental 21.0.0
219
173
  */
220
- declare const REQUIRED: MetadataKey<Signal<boolean>, boolean, boolean>;
174
+ declare const REQUIRED: AggregateMetadataKey<boolean, boolean>;
221
175
  /**
222
- * A {@link MetadataKey} representing the min value of the field.
176
+ * An {@link AggregateMetadataKey} representing the min value of the field.
223
177
  *
224
178
  * @category validation
225
179
  * @experimental 21.0.0
226
180
  */
227
- declare const MIN: MetadataKey<Signal<number | undefined>, number | undefined, number | undefined>;
181
+ declare const MIN: AggregateMetadataKey<number | undefined, number | undefined>;
228
182
  /**
229
- * A {@link MetadataKey} representing the max value of the field.
183
+ * An {@link AggregateMetadataKey} representing the max value of the field.
230
184
  *
231
185
  * @category validation
232
186
  * @experimental 21.0.0
233
187
  */
234
- declare const MAX: MetadataKey<Signal<number | undefined>, number | undefined, number | undefined>;
188
+ declare const MAX: AggregateMetadataKey<number | undefined, number | undefined>;
235
189
  /**
236
- * A {@link MetadataKey} representing the min length of the field.
190
+ * An {@link AggregateMetadataKey} representing the min length of the field.
237
191
  *
238
192
  * @category validation
239
193
  * @experimental 21.0.0
240
194
  */
241
- declare const MIN_LENGTH: MetadataKey<Signal<number | undefined>, number | undefined, number | undefined>;
195
+ declare const MIN_LENGTH: AggregateMetadataKey<number | undefined, number | undefined>;
242
196
  /**
243
- * A {@link MetadataKey} representing the max length of the field.
197
+ * An {@link AggregateMetadataKey} representing the max length of the field.
244
198
  *
245
199
  * @category validation
246
200
  * @experimental 21.0.0
247
201
  */
248
- declare const MAX_LENGTH: MetadataKey<Signal<number | undefined>, number | undefined, number | undefined>;
202
+ declare const MAX_LENGTH: AggregateMetadataKey<number | undefined, number | undefined>;
249
203
  /**
250
- * A {@link MetadataKey} representing the patterns the field must match.
204
+ * An {@link AggregateMetadataKey} representing the patterns the field must match.
251
205
  *
252
206
  * @category validation
253
207
  * @experimental 21.0.0
254
208
  */
255
- declare const PATTERN: MetadataKey<Signal<RegExp[]>, RegExp | undefined, RegExp[]>;
209
+ declare const PATTERN: AggregateMetadataKey<RegExp[], RegExp | undefined>;
256
210
 
257
211
  /**
258
- * Symbol used to retain generic type information when it would otherwise be lost.
212
+ * Options used to create a `ValidationError`.
259
213
  */
260
- declare const ɵɵTYPE: unique symbol;
214
+ interface ValidationErrorOptions {
215
+ /** Human readable error message. */
216
+ message?: string;
217
+ }
261
218
  /**
262
- * A type that represents either a single value of type `T` or a readonly array of `T`.
263
- * @template T The type of the value(s).
219
+ * A type that requires the given type `T` to have a `field` property.
220
+ * @template T The type to add a `field` to.
264
221
  *
265
222
  * @experimental 21.0.0
266
223
  */
267
- type OneOrMany<T> = T | readonly T[];
224
+ type WithField<T> = T & {
225
+ field: FieldTree<unknown>;
226
+ };
268
227
  /**
269
- * The kind of `FieldPath` (`Root`, `Child` of another `FieldPath`, or `Item` in a `FieldPath` array)
228
+ * A type that allows the given type `T` to optionally have a `field` property.
229
+ * @template T The type to optionally add a `field` to.
270
230
  *
271
231
  * @experimental 21.0.0
272
232
  */
273
- type PathKind = PathKind.Root | PathKind.Child | PathKind.Item;
274
- declare namespace PathKind {
275
- /**
276
- * The `PathKind` for a `FieldPath` that is at the root of its field tree.
277
- */
278
- interface Root {
279
- /**
280
- * The `ɵɵTYPE` is constructed to allow the `extends` clause on `Child` and `Item` to narrow the
281
- * type. Another way to think about this is, if we have a function that expects this kind of
282
- * path, the `ɵɵTYPE` lists the kinds of path we are allowed to pass to it.
283
- */
284
- [ɵɵTYPE]: 'root' | 'child' | 'item';
285
- }
286
- /**
287
- * The `PathKind` for a `FieldPath` that is a child of another `FieldPath`.
288
- */
289
- interface Child extends PathKind.Root {
290
- [ɵɵTYPE]: 'child' | 'item';
291
- }
292
- /**
293
- * The `PathKind` for a `FieldPath` that is an item in a `FieldPath` array.
294
- */
295
- interface Item extends PathKind.Child {
296
- [ɵɵTYPE]: 'item';
297
- }
298
- }
233
+ type WithOptionalField<T> = Omit<T, 'field'> & {
234
+ field?: FieldTree<unknown>;
235
+ };
299
236
  /**
300
- * A status indicating whether a field is unsubmitted, submitted, or currently submitting.
237
+ * A type that ensures the given type `T` does not have a `field` property.
238
+ * @template T The type to remove the `field` from.
301
239
  *
302
- * @category types
303
240
  * @experimental 21.0.0
304
241
  */
305
- type SubmittedStatus = 'unsubmitted' | 'submitted' | 'submitting';
242
+ type WithoutField<T> = T & {
243
+ field: never;
244
+ };
306
245
  /**
307
- * A reason for a field's disablement.
246
+ * Create a required error associated with the target field
247
+ * @param options The validation error options
308
248
  *
309
- * @category logic
310
249
  * @experimental 21.0.0
311
250
  */
312
- interface DisabledReason {
313
- /** The field that is disabled. */
314
- readonly field: FieldTree<unknown>;
315
- /** A user-facing message describing the reason for the disablement. */
316
- readonly message?: string;
317
- }
251
+ declare function requiredError(options: WithField<ValidationErrorOptions>): RequiredValidationError;
318
252
  /**
319
- * The absence of an error which indicates a successful validation result.
253
+ * Create a required error
254
+ * @param options The optional validation error options
320
255
  *
321
- * @category types
256
+ * @category validation
322
257
  * @experimental 21.0.0
323
258
  */
324
- type ValidationSuccess = null | undefined | void;
259
+ declare function requiredError(options?: ValidationErrorOptions): WithoutField<RequiredValidationError>;
325
260
  /**
326
- * The result of running a tree validation function.
327
- *
328
- * The result may be one of the following:
329
- * 1. A {@link ValidationSuccess} to indicate no errors.
330
- * 2. A {@link ValidationError} without a field to indicate an error on the field being validated.
331
- * 3. A {@link ValidationError} with a field to indicate an error on the target field.
332
- * 4. A list of {@link ValidationError} with or without fields to indicate multiple errors.
333
- *
334
- * @template E the type of error (defaults to {@link ValidationError}).
261
+ * Create a min value error associated with the target field
262
+ * @param min The min value constraint
263
+ * @param options The validation error options
335
264
  *
336
- * @category types
265
+ * @category validation
337
266
  * @experimental 21.0.0
338
267
  */
339
- type TreeValidationResult<E extends ValidationError.WithOptionalField = ValidationError.WithOptionalField> = ValidationSuccess | OneOrMany<E>;
268
+ declare function minError(min: number, options: WithField<ValidationErrorOptions>): MinValidationError;
340
269
  /**
341
- * A validation result where all errors explicitly define their target field.
270
+ * Create a min value error
271
+ * @param min The min value constraint
272
+ * @param options The optional validation error options
342
273
  *
343
- * The result may be one of the following:
344
- * 1. A {@link ValidationSuccess} to indicate no errors.
345
- * 2. A {@link ValidationError} with a field to indicate an error on the target field.
346
- * 3. A list of {@link ValidationError} with fields to indicate multiple errors.
274
+ * @category validation
275
+ * @experimental 21.0.0
276
+ */
277
+ declare function minError(min: number, options?: ValidationErrorOptions): WithoutField<MinValidationError>;
278
+ /**
279
+ * Create a max value error associated with the target field
280
+ * @param max The max value constraint
281
+ * @param options The validation error options
347
282
  *
348
- * @template E the type of error (defaults to {@link ValidationError}).
283
+ * @category validation
284
+ * @experimental 21.0.0
285
+ */
286
+ declare function maxError(max: number, options: WithField<ValidationErrorOptions>): MaxValidationError;
287
+ /**
288
+ * Create a max value error
289
+ * @param max The max value constraint
290
+ * @param options The optional validation error options
349
291
  *
350
- * @category types
292
+ * @category validation
351
293
  * @experimental 21.0.0
352
294
  */
353
- type ValidationResult<E extends ValidationError = ValidationError> = ValidationSuccess | OneOrMany<E>;
295
+ declare function maxError(max: number, options?: ValidationErrorOptions): WithoutField<MaxValidationError>;
354
296
  /**
355
- * An asynchronous validation result where all errors explicitly define their target field.
297
+ * Create a minLength error associated with the target field
298
+ * @param minLength The minLength constraint
299
+ * @param options The validation error options
356
300
  *
357
- * The result may be one of the following:
358
- * 1. A {@link ValidationResult} to indicate the result if resolved.
359
- * 5. 'pending' if the validation is not yet resolved.
301
+ * @category validation
302
+ * @experimental 21.0.0
303
+ */
304
+ declare function minLengthError(minLength: number, options: WithField<ValidationErrorOptions>): MinLengthValidationError;
305
+ /**
306
+ * Create a minLength error
307
+ * @param minLength The minLength constraint
308
+ * @param options The optional validation error options
360
309
  *
361
- * @template E the type of error (defaults to {@link ValidationError}).
310
+ * @category validation
311
+ * @experimental 21.0.0
312
+ */
313
+ declare function minLengthError(minLength: number, options?: ValidationErrorOptions): WithoutField<MinLengthValidationError>;
314
+ /**
315
+ * Create a maxLength error associated with the target field
316
+ * @param maxLength The maxLength constraint
317
+ * @param options The validation error options
362
318
  *
363
- * @category types
319
+ * @category validation
364
320
  * @experimental 21.0.0
365
321
  */
366
- type AsyncValidationResult<E extends ValidationError = ValidationError> = ValidationResult<E> | 'pending';
322
+ declare function maxLengthError(maxLength: number, options: WithField<ValidationErrorOptions>): MaxLengthValidationError;
367
323
  /**
368
- * An object that represents a tree of fields in a form. This includes both primitive value fields
369
- * (e.g. fields that contain a `string` or `number`), as well as "grouping fields" that contain
370
- * sub-fields. `FieldTree` objects are arranged in a tree whose structure mimics the structure of the
371
- * underlying data. For example a `FieldTree<{x: number}>` has a property `x` which contains a
372
- * `FieldTree<number>`. To access the state associated with a field, call it as a function.
324
+ * Create a maxLength error
325
+ * @param maxLength The maxLength constraint
326
+ * @param options The optional validation error options
373
327
  *
374
- * @template TValue The type of the data which the field is wrapped around.
375
- * @template TKey The type of the property key which this field resides under in its parent.
328
+ * @category validation
329
+ * @experimental 21.0.0
330
+ */
331
+ declare function maxLengthError(maxLength: number, options?: ValidationErrorOptions): WithoutField<MaxLengthValidationError>;
332
+ /**
333
+ * Create a pattern matching error associated with the target field
334
+ * @param pattern The violated pattern
335
+ * @param options The validation error options
376
336
  *
377
- * @category types
337
+ * @category validation
378
338
  * @experimental 21.0.0
379
339
  */
380
- type FieldTree<TModel, TKey extends string | number = string | number> = (() => [TModel] extends [AbstractControl] ? CompatFieldState<TModel, TKey> : FieldState<TModel, TKey>) & ([TModel] extends [AbstractControl] ? object : [TModel] extends [Array<infer U>] ? ReadonlyArrayLike<MaybeFieldTree<U, number>> : TModel extends Record<string, any> ? Subfields<TModel> : object);
340
+ declare function patternError(pattern: RegExp, options: WithField<ValidationErrorOptions>): PatternValidationError;
381
341
  /**
382
- * The sub-fields that a user can navigate to from a `FieldTree<TModel>`.
342
+ * Create a pattern matching error
343
+ * @param pattern The violated pattern
344
+ * @param options The optional validation error options
383
345
  *
384
- * @template TModel The type of the data which the parent field is wrapped around.
346
+ * @category validation
347
+ * @experimental 21.0.0
348
+ */
349
+ declare function patternError(pattern: RegExp, options?: ValidationErrorOptions): WithoutField<PatternValidationError>;
350
+ /**
351
+ * Create an email format error associated with the target field
352
+ * @param options The validation error options
385
353
  *
354
+ * @category validation
386
355
  * @experimental 21.0.0
387
356
  */
388
- type Subfields<TModel> = {
389
- readonly [K in keyof TModel as TModel[K] extends Function ? never : K]: MaybeFieldTree<TModel[K], string>;
390
- } & {
391
- [Symbol.iterator](): Iterator<[string, MaybeFieldTree<TModel[keyof TModel], string>]>;
392
- };
357
+ declare function emailError(options: WithField<ValidationErrorOptions>): EmailValidationError;
393
358
  /**
394
- * An iterable object with the same shape as a readonly array.
359
+ * Create an email format error
360
+ * @param options The optional validation error options
395
361
  *
396
- * @template T The array item type.
362
+ * @category validation
363
+ * @experimental 21.0.0
364
+ */
365
+ declare function emailError(options?: ValidationErrorOptions): WithoutField<EmailValidationError>;
366
+ /**
367
+ * Create a standard schema issue error associated with the target field
368
+ * @param issue The standard schema issue
369
+ * @param options The validation error options
397
370
  *
371
+ * @category validation
398
372
  * @experimental 21.0.0
399
373
  */
400
- type ReadonlyArrayLike<T> = Pick<ReadonlyArray<T>, number | 'length' | typeof Symbol.iterator>;
374
+ declare function standardSchemaError(issue: StandardSchemaV1.Issue, options: WithField<ValidationErrorOptions>): StandardSchemaValidationError;
401
375
  /**
402
- * Helper type for defining `FieldTree`. Given a type `TValue` that may include `undefined`, it extracts
403
- * the `undefined` outside the `FieldTree` type.
376
+ * Create a standard schema issue error
377
+ * @param issue The standard schema issue
378
+ * @param options The optional validation error options
404
379
  *
405
- * For example `MaybeField<{a: number} | undefined, TKey>` would be equivalent to
406
- * `undefined | FieldTree<{a: number}, TKey>`.
380
+ * @category validation
381
+ * @experimental 21.0.0
382
+ */
383
+ declare function standardSchemaError(issue: StandardSchemaV1.Issue, options?: ValidationErrorOptions): WithoutField<StandardSchemaValidationError>;
384
+ /**
385
+ * Create a custom error associated with the target field
386
+ * @param obj The object to create an error from
407
387
  *
408
- * @template TModel The type of the data which the field is wrapped around.
409
- * @template TKey The type of the property key which this field resides under in its parent.
388
+ * @category validation
389
+ * @experimental 21.0.0
390
+ */
391
+ declare function customError<E extends Partial<ValidationError.WithField>>(obj: WithField<E>): CustomValidationError;
392
+ /**
393
+ * Create a custom error
394
+ * @param obj The object to create an error from
410
395
  *
396
+ * @category validation
411
397
  * @experimental 21.0.0
412
398
  */
413
- type MaybeFieldTree<TModel, TKey extends string | number = string | number> = (TModel & undefined) | FieldTree<Exclude<TModel, undefined>, TKey>;
399
+ declare function customError<E extends Partial<ValidationError.WithField>>(obj?: E): WithoutField<CustomValidationError>;
414
400
  /**
415
- * Contains all of the state (e.g. value, statuses, etc.) associated with a `FieldTree`, exposed as
416
- * signals.
401
+ * Common interface for all validation errors.
417
402
  *
418
- * @category structure
403
+ * This can be returned from validators.
404
+ *
405
+ * It's also used by the creation functions to create an instance
406
+ * (e.g. `requiredError`, `minError`, etc.).
407
+ *
408
+ * @category validation
419
409
  * @experimental 21.0.0
420
410
  */
421
- interface FieldState<TValue, TKey extends string | number = string | number> extends _FieldState<TValue> {
422
- /**
423
- * A signal indicating whether field value has been changed by user.
424
- */
425
- readonly dirty: Signal<boolean>;
426
- /**
427
- * A signal indicating whether a field is hidden.
428
- *
429
- * When a field is hidden it is ignored when determining the valid, touched, and dirty states.
430
- *
431
- * Note: This doesn't hide the field in the template, that must be done manually.
432
- * ```
433
- * @if (!field.hidden()) {
434
- * ...
435
- * }
436
- * ```
437
- */
438
- readonly hidden: Signal<boolean>;
439
- readonly disabledReasons: Signal<readonly DisabledReason[]>;
440
- readonly errors: Signal<ValidationError.WithField[]>;
441
- /**
442
- * A signal containing the {@link errors} of the field and its descendants.
443
- */
444
- readonly errorSummary: Signal<ValidationError.WithField[]>;
411
+ interface ValidationError {
412
+ /** Identifies the kind of error. */
413
+ readonly kind: string;
414
+ /** Human readable error message. */
415
+ readonly message?: string;
416
+ }
417
+ declare namespace ValidationError {
445
418
  /**
446
- * A signal indicating whether the field's value is currently valid.
447
- *
448
- * Note: `valid()` is not the same as `!invalid()`.
449
- * - `valid()` is `true` when there are no validation errors *and* no pending validators.
450
- * - `invalid()` is `true` when there are validation errors, regardless of pending validators.
419
+ * Validation error with a field.
451
420
  *
452
- * Ex: consider the situation where a field has 3 validators, 2 of which have no errors and 1 of
453
- * which is still pending. In this case `valid()` is `false` because of the pending validator.
454
- * However `invalid()` is also `false` because there are no errors.
421
+ * This is returned from field state, e.g., catField.errors() would be of a list of errors with
422
+ * `field: catField` bound to state.
455
423
  */
456
- readonly valid: Signal<boolean>;
424
+ interface WithField extends ValidationError {
425
+ /** The field associated with this error. */
426
+ readonly field: FieldTree<unknown>;
427
+ }
457
428
  /**
458
- * A signal indicating whether the field's value is currently invalid.
459
- *
460
- * Note: `invalid()` is not the same as `!valid()`.
461
- * - `invalid()` is `true` when there are validation errors, regardless of pending validators.
462
- * - `valid()` is `true` when there are no validation errors *and* no pending validators.
429
+ * Validation error with optional field.
463
430
  *
464
- * Ex: consider the situation where a field has 3 validators, 2 of which have no errors and 1 of
465
- * which is still pending. In this case `invalid()` is `false` because there are no errors.
466
- * However `valid()` is also `false` because of the pending validator.
467
- */
468
- readonly invalid: Signal<boolean>;
469
- /**
470
- * Whether there are any validators still pending for this field.
471
- */
472
- readonly pending: Signal<boolean>;
473
- /**
474
- * A signal indicating whether the field is currently in the process of being submitted.
475
- */
476
- readonly submitting: Signal<boolean>;
477
- /**
478
- * The property key in the parent field under which this field is stored. If the parent field is
479
- * array-valued, for example, this is the index of this field in that array.
480
- */
481
- readonly keyInParent: Signal<TKey>;
482
- /**
483
- * The {@link Field} directives that bind this field to a UI control.
484
- */
485
- readonly fieldBindings: Signal<readonly Field<unknown>[]>;
486
- /**
487
- * Reads a metadata value from the field.
488
- * @param key The metadata key to read.
431
+ * This is generally used in places where the result might have a field.
432
+ * e.g., as a result of a `validateTree`, or when handling form submission.
489
433
  */
490
- metadata<M>(key: MetadataKey<M, any, any>): M | undefined;
434
+ interface WithOptionalField extends ValidationError {
435
+ /** The field associated with this error. */
436
+ readonly field?: FieldTree<unknown>;
437
+ }
491
438
  /**
492
- * Resets the {@link touched} and {@link dirty} state of the field and its descendants.
493
- *
494
- * Note this does not change the data model, which can be reset directly if desired.
439
+ * Validation error with no field.
495
440
  *
496
- * @param value Optional value to set to the form. If not passed, the value will not be changed.
441
+ * This is used to strongly enforce that fields are not allowed in validation result.
497
442
  */
498
- reset(value?: TValue): void;
443
+ interface WithoutField extends ValidationError {
444
+ /** The field associated with this error. */
445
+ readonly field?: never;
446
+ }
499
447
  }
500
448
  /**
501
- * This is FieldState also providing access to the wrapped FormControl.
449
+ * A custom error that may contain additional properties
502
450
  *
503
- * @category interop
451
+ * @category validation
504
452
  * @experimental 21.0.0
505
453
  */
506
- type CompatFieldState<TControl extends AbstractControl, TKey extends string | number = string | number> = FieldState<TControl extends AbstractControl<unknown, infer TValue> ? TValue : never, TKey> & {
507
- control: Signal<TControl>;
508
- };
509
- /**
510
- * Allows declaring whether the Rules are supported for a given path.
511
- *
512
- * @experimental 21.0.0
513
- **/
514
- type SchemaPathRules = SchemaPathRules.Supported | SchemaPathRules.Unsupported;
515
- declare namespace SchemaPathRules {
516
- /**
517
- * Used for paths that support settings rules.
518
- */
519
- type Supported = 1;
454
+ declare class CustomValidationError implements ValidationError {
455
+ /** Brand the class to avoid Typescript structural matching */
456
+ private __brand;
520
457
  /**
521
- * Used for paths that do not support settings rules, e.g., compatPath.
458
+ * Allow the user to attach arbitrary other properties.
522
459
  */
523
- type Unsupported = 2;
460
+ [key: PropertyKey]: unknown;
461
+ /** Identifies the kind of error. */
462
+ readonly kind: string;
463
+ /** The field associated with this error. */
464
+ readonly field: FieldTree<unknown>;
465
+ /** Human readable error message. */
466
+ readonly message?: string;
467
+ constructor(options?: ValidationErrorOptions);
524
468
  }
525
469
  /**
526
- * An object that represents a location in the `FieldTree` tree structure and is used to bind logic to a
527
- * particular part of the structure prior to the creation of the form. Because the `FieldPath`
528
- * exists prior to the form's creation, it cannot be used to access any of the field state.
529
- *
530
- * @template TValue The type of the data which the form is wrapped around.
531
- * @template TPathKind The kind of path (root field, child field, or item of an array)
470
+ * Internal version of `NgValidationError`, we create this separately so we can change its type on
471
+ * the exported version to a type union of the possible sub-classes.
532
472
  *
533
- * @category types
534
473
  * @experimental 21.0.0
535
474
  */
536
- type SchemaPath<TValue, TSupportsRules extends SchemaPathRules = SchemaPathRules.Supported, TPathKind extends PathKind = PathKind.Root> = {
537
- [ɵɵTYPE]: {
538
- value: () => TValue;
539
- supportsRules: TSupportsRules;
540
- pathKind: TPathKind;
541
- };
542
- };
475
+ declare abstract class _NgValidationError implements ValidationError {
476
+ /** Brand the class to avoid Typescript structural matching */
477
+ private __brand;
478
+ /** Identifies the kind of error. */
479
+ readonly kind: string;
480
+ /** The field associated with this error. */
481
+ readonly field: FieldTree<unknown>;
482
+ /** Human readable error message. */
483
+ readonly message?: string;
484
+ constructor(options?: ValidationErrorOptions);
485
+ }
543
486
  /**
544
- * Schema path used if the value is an AbstractControl.
487
+ * An error used to indicate that a required field is empty.
545
488
  *
546
- * @category interop
489
+ * @category validation
547
490
  * @experimental 21.0.0
548
491
  */
549
- type CompatSchemaPath<TControl extends AbstractControl, TPathKind extends PathKind = PathKind.Root> = SchemaPath<TControl extends AbstractControl<unknown, infer TValue> ? TValue : never, SchemaPathRules.Unsupported, TPathKind> & {
550
- [ɵɵTYPE]: {
551
- control: TControl;
552
- };
553
- };
492
+ declare class RequiredValidationError extends _NgValidationError {
493
+ readonly kind = "required";
494
+ }
554
495
  /**
555
- * Nested schema path.
556
- *
557
- * It mirrors the structure of a given data structure, and allows applying rules to the appropriate
558
- * fields.
496
+ * An error used to indicate that a value is lower than the minimum allowed.
559
497
  *
498
+ * @category validation
560
499
  * @experimental 21.0.0
561
500
  */
562
- type SchemaPathTree<TModel, TPathKind extends PathKind = PathKind.Root> = ([TModel] extends [AbstractControl] ? CompatSchemaPath<TModel, TPathKind> : SchemaPath<TModel, SchemaPathRules.Supported, TPathKind>) & (TModel extends AbstractControl ? unknown : TModel extends Array<any> ? unknown : TModel extends Record<string, any> ? {
563
- [K in keyof TModel]: MaybeSchemaPathTree<TModel[K], PathKind.Child>;
564
- } : unknown);
501
+ declare class MinValidationError extends _NgValidationError {
502
+ readonly min: number;
503
+ readonly kind = "min";
504
+ constructor(min: number, options?: ValidationErrorOptions);
505
+ }
565
506
  /**
566
- * Helper type for defining `FieldPath`. Given a type `TValue` that may include `undefined`, it
567
- * extracts the `undefined` outside the `FieldPath` type.
568
- *
569
- * For example `MaybeFieldPath<{a: number} | undefined, PathKind.Child>` would be equivalent to
570
- * `undefined | FieldTree<{a: number}, PathKind.child>`.
571
- *
572
- * @template TValue The type of the data which the field is wrapped around.
573
- * @template TPathKind The kind of path (root field, child field, or item of an array)
507
+ * An error used to indicate that a value is higher than the maximum allowed.
574
508
  *
509
+ * @category validation
575
510
  * @experimental 21.0.0
576
511
  */
577
- type MaybeSchemaPathTree<TModel, TPathKind extends PathKind = PathKind.Root> = (TModel & undefined) | SchemaPathTree<Exclude<TModel, undefined>, TPathKind>;
512
+ declare class MaxValidationError extends _NgValidationError {
513
+ readonly max: number;
514
+ readonly kind = "max";
515
+ constructor(max: number, options?: ValidationErrorOptions);
516
+ }
578
517
  /**
579
- * Defines logic for a form.
580
- *
581
- * @template TValue The type of data stored in the form that this schema is attached to.
518
+ * An error used to indicate that a value is shorter than the minimum allowed length.
582
519
  *
583
- * @category types
520
+ * @category validation
584
521
  * @experimental 21.0.0
585
522
  */
586
- type Schema<in TModel> = {
587
- [ɵɵTYPE]: SchemaFn<TModel, PathKind.Root>;
588
- };
523
+ declare class MinLengthValidationError extends _NgValidationError {
524
+ readonly minLength: number;
525
+ readonly kind = "minLength";
526
+ constructor(minLength: number, options?: ValidationErrorOptions);
527
+ }
589
528
  /**
590
- * Function that defines rules for a schema.
591
- *
592
- * @template TModel The type of data stored in the form that this schema function is attached to.
593
- * @template TPathKind The kind of path this schema function can be bound to.
529
+ * An error used to indicate that a value is longer than the maximum allowed length.
594
530
  *
595
- * @category types
531
+ * @category validation
596
532
  * @experimental 21.0.0
597
533
  */
598
- type SchemaFn<TModel, TPathKind extends PathKind = PathKind.Root> = (p: SchemaPathTree<TModel, TPathKind>) => void;
534
+ declare class MaxLengthValidationError extends _NgValidationError {
535
+ readonly maxLength: number;
536
+ readonly kind = "maxLength";
537
+ constructor(maxLength: number, options?: ValidationErrorOptions);
538
+ }
599
539
  /**
600
- * A schema or schema definition function.
601
- *
602
- * @template TModel The type of data stored in the form that this schema function is attached to.
603
- * @template TPathKind The kind of path this schema function can be bound to.
540
+ * An error used to indicate that a value does not match the required pattern.
604
541
  *
605
- * @category types
542
+ * @category validation
606
543
  * @experimental 21.0.0
607
544
  */
608
- type SchemaOrSchemaFn<TModel, TPathKind extends PathKind = PathKind.Root> = Schema<TModel> | SchemaFn<TModel, TPathKind>;
545
+ declare class PatternValidationError extends _NgValidationError {
546
+ readonly pattern: RegExp;
547
+ readonly kind = "pattern";
548
+ constructor(pattern: RegExp, options?: ValidationErrorOptions);
549
+ }
609
550
  /**
610
- * A function that receives the `FieldContext` for the field the logic is bound to and returns
611
- * a specific result type.
612
- *
613
- * @template TValue The data type for the field the logic is bound to.
614
- * @template TReturn The type of the result returned by the logic function.
615
- * @template TPathKind The kind of path the logic is applied to (root field, child field, or item of an array)
551
+ * An error used to indicate that a value is not a valid email.
616
552
  *
617
- * @category types
553
+ * @category validation
618
554
  * @experimental 21.0.0
619
555
  */
620
- type LogicFn<TValue, TReturn, TPathKind extends PathKind = PathKind.Root> = (ctx: FieldContext<TValue, TPathKind>) => TReturn;
556
+ declare class EmailValidationError extends _NgValidationError {
557
+ readonly kind = "email";
558
+ }
621
559
  /**
622
- * A function that takes the `FieldContext` for the field being validated and returns a
623
- * `ValidationResult` indicating errors for the field.
624
- *
625
- * @template TValue The type of value stored in the field being validated
626
- * @template TPathKind The kind of path being validated (root field, child field, or item of an array)
560
+ * An error used to indicate an issue validating against a standard schema.
627
561
  *
628
562
  * @category validation
629
563
  * @experimental 21.0.0
630
564
  */
631
- type FieldValidator<TValue, TPathKind extends PathKind = PathKind.Root> = LogicFn<TValue, ValidationResult<ValidationError.WithoutField>, TPathKind>;
565
+ declare class StandardSchemaValidationError extends _NgValidationError {
566
+ readonly issue: StandardSchemaV1.Issue;
567
+ readonly kind = "standardSchema";
568
+ constructor(issue: StandardSchemaV1.Issue, options?: ValidationErrorOptions);
569
+ }
632
570
  /**
633
- * A function that takes the `FieldContext` for the field being validated and returns a
634
- * `TreeValidationResult` indicating errors for the field and its sub-fields.
571
+ * The base class for all built-in, non-custom errors. This class can be used to check if an error
572
+ * is one of the standard kinds, allowing you to switch on the kind to further narrow the type.
635
573
  *
636
- * @template TValue The type of value stored in the field being validated
637
- * @template TPathKind The kind of path being validated (root field, child field, or item of an array)
574
+ * @example
575
+ * ```ts
576
+ * const f = form(...);
577
+ * for (const e of form().errors()) {
578
+ * if (e instanceof NgValidationError) {
579
+ * switch(e.kind) {
580
+ * case 'required':
581
+ * console.log('This is required!');
582
+ * break;
583
+ * case 'min':
584
+ * console.log(`Must be at least ${e.min}`);
585
+ * break;
586
+ * ...
587
+ * }
588
+ * }
589
+ * }
590
+ * ```
638
591
  *
639
- * @category types
592
+ * @category validation
640
593
  * @experimental 21.0.0
641
594
  */
642
- type TreeValidator<TValue, TPathKind extends PathKind = PathKind.Root> = LogicFn<TValue, TreeValidationResult, TPathKind>;
595
+ declare const NgValidationError: abstract new () => NgValidationError;
596
+ type NgValidationError = RequiredValidationError | MinValidationError | MaxValidationError | MinLengthValidationError | MaxLengthValidationError | PatternValidationError | EmailValidationError | StandardSchemaValidationError;
597
+
643
598
  /**
644
- * A function that takes the `FieldContext` for the field being validated and returns a
645
- * `ValidationResult` indicating errors for the field and its sub-fields. In a `Validator` all
646
- * errors must explicitly define their target field.
647
- *
648
- * @template TValue The type of value stored in the field being validated
649
- * @template TPathKind The kind of path being validated (root field, child field, or item of an array)
650
- *
651
- * @category types
652
- * @experimental 21.0.0
599
+ * Symbol used to retain generic type information when it would otherwise be lost.
653
600
  */
654
- type Validator<TValue, TPathKind extends PathKind = PathKind.Root> = LogicFn<TValue, ValidationResult, TPathKind>;
601
+ declare const ɵɵTYPE: unique symbol;
655
602
  /**
656
- * Provides access to the state of the current field as well as functions that can be used to look
657
- * up state of other fields based on a `FieldPath`.
603
+ * A type that represents either a single value of type `T` or a readonly array of `T`.
604
+ * @template T The type of the value(s).
658
605
  *
659
- * @category types
660
606
  * @experimental 21.0.0
661
607
  */
662
- type FieldContext<TValue, TPathKind extends PathKind = PathKind.Root> = TPathKind extends PathKind.Item ? ItemFieldContext<TValue> : TPathKind extends PathKind.Child ? ChildFieldContext<TValue> : RootFieldContext<TValue>;
608
+ type OneOrMany<T> = T | readonly T[];
663
609
  /**
664
- * The base field context that is available for all fields.
610
+ * The kind of `FieldPath` (`Root`, `Child` of another `FieldPath`, or `Item` in a `FieldPath` array)
665
611
  *
666
612
  * @experimental 21.0.0
667
613
  */
668
- interface RootFieldContext<TValue> {
669
- /** A signal containing the value of the current field. */
670
- readonly value: Signal<TValue>;
671
- /** The state of the current field. */
672
- readonly state: FieldState<TValue>;
673
- /** The current field. */
674
- readonly field: FieldTree<TValue>;
675
- /** Gets the value of the field represented by the given path. */
676
- valueOf<PValue>(p: SchemaPath<PValue, SchemaPathRules>): PValue;
677
- /** Gets the state of the field represented by the given path. */
678
- stateOf<PControl extends AbstractControl>(p: CompatSchemaPath<PControl>): CompatFieldState<PControl>;
679
- stateOf<PValue>(p: SchemaPath<PValue, SchemaPathRules>): FieldState<PValue>;
680
- /** Gets the field represented by the given path. */
681
- fieldTreeOf<PModel>(p: SchemaPathTree<PModel>): FieldTree<PModel>;
682
- /** The list of keys that lead from the root field to the current field. */
683
- readonly pathKeys: Signal<readonly string[]>;
614
+ type PathKind = PathKind.Root | PathKind.Child | PathKind.Item;
615
+ declare namespace PathKind {
616
+ /**
617
+ * The `PathKind` for a `FieldPath` that is at the root of its field tree.
618
+ */
619
+ interface Root {
620
+ /**
621
+ * The `ɵɵTYPE` is constructed to allow the `extends` clause on `Child` and `Item` to narrow the
622
+ * type. Another way to think about this is, if we have a function that expects this kind of
623
+ * path, the `ɵɵTYPE` lists the kinds of path we are allowed to pass to it.
624
+ */
625
+ [ɵɵTYPE]: 'root' | 'child' | 'item';
626
+ }
627
+ /**
628
+ * The `PathKind` for a `FieldPath` that is a child of another `FieldPath`.
629
+ */
630
+ interface Child extends PathKind.Root {
631
+ [ɵɵTYPE]: 'child' | 'item';
632
+ }
633
+ /**
634
+ * The `PathKind` for a `FieldPath` that is an item in a `FieldPath` array.
635
+ */
636
+ interface Item extends PathKind.Child {
637
+ [ɵɵTYPE]: 'item';
638
+ }
684
639
  }
685
640
  /**
686
- * Field context that is available for all fields that are a child of another field.
641
+ * A status indicating whether a field is unsubmitted, submitted, or currently submitting.
687
642
  *
688
- * @category structure
643
+ * @category types
689
644
  * @experimental 21.0.0
690
645
  */
691
- interface ChildFieldContext<TValue> extends RootFieldContext<TValue> {
692
- /** The key of the current field in its parent field. */
693
- readonly key: Signal<string>;
694
- }
646
+ type SubmittedStatus = 'unsubmitted' | 'submitted' | 'submitting';
695
647
  /**
696
- * Field context that is available for all fields that are an item in an array field.
648
+ * A reason for a field's disablement.
697
649
  *
650
+ * @category logic
698
651
  * @experimental 21.0.0
699
652
  */
700
- interface ItemFieldContext<TValue> extends ChildFieldContext<TValue> {
701
- /** The index of the current field in its parent field. */
702
- readonly index: Signal<number>;
653
+ interface DisabledReason {
654
+ /** The field that is disabled. */
655
+ readonly field: FieldTree<unknown>;
656
+ /** A user-facing message describing the reason for the disablement. */
657
+ readonly message?: string;
703
658
  }
704
659
  /**
705
- * Gets the item type of an object that is possibly an array.
660
+ * The absence of an error which indicates a successful validation result.
706
661
  *
662
+ * @category types
707
663
  * @experimental 21.0.0
708
664
  */
709
- type ItemType<T extends Object> = T extends ReadonlyArray<any> ? T[number] : T[keyof T];
665
+ type ValidationSuccess = null | undefined | void;
710
666
  /**
711
- * A function that defines custom debounce logic for a field.
712
- *
713
- * @param context The field context.
714
- * @param abortSignal An `AbortSignal` used to communicate that the debounced operation was aborted.
715
- * @returns A `Promise<void>` to debounce an update, or `void` to apply an update immediately.
716
- * @template TValue The type of value stored in the field.
717
- * @template TPathKind The kind of path the debouncer is applied to (root field, child field, or item of an array).
667
+ * The result of running a tree validation function.
718
668
  *
719
- * @experimental 21.0.0
720
- */
721
- type Debouncer<TValue, TPathKind extends PathKind = PathKind.Root> = (context: FieldContext<TValue, TPathKind>, abortSignal: AbortSignal) => Promise<void> | void;
722
-
723
- /**
724
- * Options used to create a `ValidationError`.
725
- */
726
- interface ValidationErrorOptions {
727
- /** Human readable error message. */
728
- message?: string;
729
- }
730
- /**
731
- * A type that requires the given type `T` to have a `field` property.
732
- * @template T The type to add a `field` to.
669
+ * The result may be one of the following:
670
+ * 1. A {@link ValidationSuccess} to indicate no errors.
671
+ * 2. A {@link ValidationError} without a field to indicate an error on the field being validated.
672
+ * 3. A {@link ValidationError} with a field to indicate an error on the target field.
673
+ * 4. A list of {@link ValidationError} with or without fields to indicate multiple errors.
733
674
  *
734
- * @experimental 21.0.0
735
- */
736
- type WithField<T> = T & {
737
- field: FieldTree<unknown>;
738
- };
739
- /**
740
- * A type that allows the given type `T` to optionally have a `field` property.
741
- * @template T The type to optionally add a `field` to.
675
+ * @template E the type of error (defaults to {@link ValidationError}).
742
676
  *
677
+ * @category types
743
678
  * @experimental 21.0.0
744
679
  */
745
- type WithOptionalField<T> = Omit<T, 'field'> & {
746
- field?: FieldTree<unknown>;
747
- };
680
+ type TreeValidationResult<E extends ValidationError.WithOptionalField = ValidationError.WithOptionalField> = ValidationSuccess | OneOrMany<E>;
748
681
  /**
749
- * A type that ensures the given type `T` does not have a `field` property.
750
- * @template T The type to remove the `field` from.
682
+ * A validation result where all errors explicitly define their target field.
751
683
  *
752
- * @experimental 21.0.0
753
- */
754
- type WithoutField<T> = T & {
755
- field: never;
756
- };
757
- /**
758
- * Create a required error associated with the target field
759
- * @param options The validation error options
684
+ * The result may be one of the following:
685
+ * 1. A {@link ValidationSuccess} to indicate no errors.
686
+ * 2. A {@link ValidationError} with a field to indicate an error on the target field.
687
+ * 3. A list of {@link ValidationError} with fields to indicate multiple errors.
760
688
  *
761
- * @experimental 21.0.0
762
- */
763
- declare function requiredError(options: WithField<ValidationErrorOptions>): RequiredValidationError;
764
- /**
765
- * Create a required error
766
- * @param options The optional validation error options
689
+ * @template E the type of error (defaults to {@link ValidationError}).
767
690
  *
768
- * @category validation
691
+ * @category types
769
692
  * @experimental 21.0.0
770
693
  */
771
- declare function requiredError(options?: ValidationErrorOptions): WithoutField<RequiredValidationError>;
694
+ type ValidationResult<E extends ValidationError = ValidationError> = ValidationSuccess | OneOrMany<E>;
772
695
  /**
773
- * Create a min value error associated with the target field
774
- * @param min The min value constraint
775
- * @param options The validation error options
696
+ * An asynchronous validation result where all errors explicitly define their target field.
776
697
  *
777
- * @category validation
778
- * @experimental 21.0.0
779
- */
780
- declare function minError(min: number, options: WithField<ValidationErrorOptions>): MinValidationError;
781
- /**
782
- * Create a min value error
783
- * @param min The min value constraint
784
- * @param options The optional validation error options
698
+ * The result may be one of the following:
699
+ * 1. A {@link ValidationResult} to indicate the result if resolved.
700
+ * 5. 'pending' if the validation is not yet resolved.
785
701
  *
786
- * @category validation
787
- * @experimental 21.0.0
788
- */
789
- declare function minError(min: number, options?: ValidationErrorOptions): WithoutField<MinValidationError>;
790
- /**
791
- * Create a max value error associated with the target field
792
- * @param max The max value constraint
793
- * @param options The validation error options
702
+ * @template E the type of error (defaults to {@link ValidationError}).
794
703
  *
795
- * @category validation
704
+ * @category types
796
705
  * @experimental 21.0.0
797
706
  */
798
- declare function maxError(max: number, options: WithField<ValidationErrorOptions>): MaxValidationError;
707
+ type AsyncValidationResult<E extends ValidationError = ValidationError> = ValidationResult<E> | 'pending';
799
708
  /**
800
- * Create a max value error
801
- * @param max The max value constraint
802
- * @param options The optional validation error options
709
+ * An object that represents a tree of fields in a form. This includes both primitive value fields
710
+ * (e.g. fields that contain a `string` or `number`), as well as "grouping fields" that contain
711
+ * sub-fields. `FieldTree` objects are arranged in a tree whose structure mimics the structure of the
712
+ * underlying data. For example a `FieldTree<{x: number}>` has a property `x` which contains a
713
+ * `FieldTree<number>`. To access the state associated with a field, call it as a function.
803
714
  *
804
- * @category validation
805
- * @experimental 21.0.0
806
- */
807
- declare function maxError(max: number, options?: ValidationErrorOptions): WithoutField<MaxValidationError>;
808
- /**
809
- * Create a minLength error associated with the target field
810
- * @param minLength The minLength constraint
811
- * @param options The validation error options
715
+ * @template TValue The type of the data which the field is wrapped around.
716
+ * @template TKey The type of the property key which this field resides under in its parent.
812
717
  *
813
- * @category validation
718
+ * @category types
814
719
  * @experimental 21.0.0
815
720
  */
816
- declare function minLengthError(minLength: number, options: WithField<ValidationErrorOptions>): MinLengthValidationError;
721
+ type FieldTree<TModel, TKey extends string | number = string | number> = (() => [TModel] extends [AbstractControl] ? CompatFieldState<TModel, TKey> : FieldState<TModel, TKey>) & ([TModel] extends [AbstractControl] ? object : [TModel] extends [Array<infer U>] ? ReadonlyArrayLike<MaybeFieldTree<U, number>> : TModel extends Record<string, any> ? Subfields<TModel> : object);
817
722
  /**
818
- * Create a minLength error
819
- * @param minLength The minLength constraint
820
- * @param options The optional validation error options
723
+ * The sub-fields that a user can navigate to from a `FieldTree<TModel>`.
724
+ *
725
+ * @template TModel The type of the data which the parent field is wrapped around.
821
726
  *
822
- * @category validation
823
727
  * @experimental 21.0.0
824
728
  */
825
- declare function minLengthError(minLength: number, options?: ValidationErrorOptions): WithoutField<MinLengthValidationError>;
729
+ type Subfields<TModel> = {
730
+ readonly [K in keyof TModel as TModel[K] extends Function ? never : K]: MaybeFieldTree<TModel[K], string>;
731
+ } & {
732
+ [Symbol.iterator](): Iterator<[string, MaybeFieldTree<TModel[keyof TModel], string>]>;
733
+ };
826
734
  /**
827
- * Create a maxLength error associated with the target field
828
- * @param maxLength The maxLength constraint
829
- * @param options The validation error options
735
+ * An iterable object with the same shape as a readonly array.
736
+ *
737
+ * @template T The array item type.
830
738
  *
831
- * @category validation
832
739
  * @experimental 21.0.0
833
740
  */
834
- declare function maxLengthError(maxLength: number, options: WithField<ValidationErrorOptions>): MaxLengthValidationError;
741
+ type ReadonlyArrayLike<T> = Pick<ReadonlyArray<T>, number | 'length' | typeof Symbol.iterator>;
835
742
  /**
836
- * Create a maxLength error
837
- * @param maxLength The maxLength constraint
838
- * @param options The optional validation error options
743
+ * Helper type for defining `FieldTree`. Given a type `TValue` that may include `undefined`, it extracts
744
+ * the `undefined` outside the `FieldTree` type.
745
+ *
746
+ * For example `MaybeField<{a: number} | undefined, TKey>` would be equivalent to
747
+ * `undefined | FieldTree<{a: number}, TKey>`.
748
+ *
749
+ * @template TModel The type of the data which the field is wrapped around.
750
+ * @template TKey The type of the property key which this field resides under in its parent.
839
751
  *
840
- * @category validation
841
752
  * @experimental 21.0.0
842
753
  */
843
- declare function maxLengthError(maxLength: number, options?: ValidationErrorOptions): WithoutField<MaxLengthValidationError>;
754
+ type MaybeFieldTree<TModel, TKey extends string | number = string | number> = (TModel & undefined) | FieldTree<Exclude<TModel, undefined>, TKey>;
844
755
  /**
845
- * Create a pattern matching error associated with the target field
846
- * @param pattern The violated pattern
847
- * @param options The validation error options
756
+ * Contains all of the state (e.g. value, statuses, etc.) associated with a `FieldTree`, exposed as
757
+ * signals.
848
758
  *
849
- * @category validation
759
+ * @category structure
850
760
  * @experimental 21.0.0
851
761
  */
852
- declare function patternError(pattern: RegExp, options: WithField<ValidationErrorOptions>): PatternValidationError;
762
+ interface FieldState<TValue, TKey extends string | number = string | number> extends _FieldState<TValue> {
763
+ /**
764
+ * A signal indicating whether field value has been changed by user.
765
+ */
766
+ readonly dirty: Signal<boolean>;
767
+ /**
768
+ * A signal indicating whether a field is hidden.
769
+ *
770
+ * When a field is hidden it is ignored when determining the valid, touched, and dirty states.
771
+ *
772
+ * Note: This doesn't hide the field in the template, that must be done manually.
773
+ * ```
774
+ * @if (!field.hidden()) {
775
+ * ...
776
+ * }
777
+ * ```
778
+ */
779
+ readonly hidden: Signal<boolean>;
780
+ readonly disabledReasons: Signal<readonly DisabledReason[]>;
781
+ readonly errors: Signal<ValidationError.WithField[]>;
782
+ /**
783
+ * A signal containing the {@link errors} of the field and its descendants.
784
+ */
785
+ readonly errorSummary: Signal<ValidationError.WithField[]>;
786
+ /**
787
+ * A signal indicating whether the field's value is currently valid.
788
+ *
789
+ * Note: `valid()` is not the same as `!invalid()`.
790
+ * - `valid()` is `true` when there are no validation errors *and* no pending validators.
791
+ * - `invalid()` is `true` when there are validation errors, regardless of pending validators.
792
+ *
793
+ * Ex: consider the situation where a field has 3 validators, 2 of which have no errors and 1 of
794
+ * which is still pending. In this case `valid()` is `false` because of the pending validator.
795
+ * However `invalid()` is also `false` because there are no errors.
796
+ */
797
+ readonly valid: Signal<boolean>;
798
+ /**
799
+ * A signal indicating whether the field's value is currently invalid.
800
+ *
801
+ * Note: `invalid()` is not the same as `!valid()`.
802
+ * - `invalid()` is `true` when there are validation errors, regardless of pending validators.
803
+ * - `valid()` is `true` when there are no validation errors *and* no pending validators.
804
+ *
805
+ * Ex: consider the situation where a field has 3 validators, 2 of which have no errors and 1 of
806
+ * which is still pending. In this case `invalid()` is `false` because there are no errors.
807
+ * However `valid()` is also `false` because of the pending validator.
808
+ */
809
+ readonly invalid: Signal<boolean>;
810
+ /**
811
+ * Whether there are any validators still pending for this field.
812
+ */
813
+ readonly pending: Signal<boolean>;
814
+ /**
815
+ * A signal indicating whether the field is currently in the process of being submitted.
816
+ */
817
+ readonly submitting: Signal<boolean>;
818
+ /**
819
+ * The property key in the parent field under which this field is stored. If the parent field is
820
+ * array-valued, for example, this is the index of this field in that array.
821
+ */
822
+ readonly keyInParent: Signal<TKey>;
823
+ /**
824
+ * The {@link Field} directives that bind this field to a UI control.
825
+ */
826
+ readonly fieldBindings: Signal<readonly Field<unknown>[]>;
827
+ /**
828
+ * Reads an aggregate metadata value from the field.
829
+ * @param key The metadata key to read.
830
+ */
831
+ metadata<M>(key: AggregateMetadataKey<M, any>): Signal<M>;
832
+ /**
833
+ * Reads a metadata value from the field.
834
+ * @param key The metadata key to read.
835
+ */
836
+ metadata<M>(key: MetadataKey<M>): M | undefined;
837
+ /**
838
+ * Checks whether the given metadata key has been defined for this field.
839
+ */
840
+ hasMetadata(key: MetadataKey<any> | AggregateMetadataKey<any, any>): boolean;
841
+ /**
842
+ * Resets the {@link touched} and {@link dirty} state of the field and its descendants.
843
+ *
844
+ * Note this does not change the data model, which can be reset directly if desired.
845
+ *
846
+ * @param value Optional value to set to the form. If not passed, the value will not be changed.
847
+ */
848
+ reset(value?: TValue): void;
849
+ }
853
850
  /**
854
- * Create a pattern matching error
855
- * @param pattern The violated pattern
856
- * @param options The optional validation error options
851
+ * This is FieldState also providing access to the wrapped FormControl.
857
852
  *
858
- * @category validation
853
+ * @category interop
859
854
  * @experimental 21.0.0
860
855
  */
861
- declare function patternError(pattern: RegExp, options?: ValidationErrorOptions): WithoutField<PatternValidationError>;
856
+ type CompatFieldState<TControl extends AbstractControl, TKey extends string | number = string | number> = FieldState<TControl extends AbstractControl<unknown, infer TValue> ? TValue : never, TKey> & {
857
+ control: Signal<TControl>;
858
+ };
862
859
  /**
863
- * Create an email format error associated with the target field
864
- * @param options The validation error options
860
+ * Allows declaring whether the Rules are supported for a given path.
865
861
  *
866
- * @category validation
867
862
  * @experimental 21.0.0
868
- */
869
- declare function emailError(options: WithField<ValidationErrorOptions>): EmailValidationError;
863
+ **/
864
+ type SchemaPathRules = SchemaPathRules.Supported | SchemaPathRules.Unsupported;
865
+ declare namespace SchemaPathRules {
866
+ /**
867
+ * Used for paths that support settings rules.
868
+ */
869
+ type Supported = 1;
870
+ /**
871
+ * Used for paths that do not support settings rules, e.g., compatPath.
872
+ */
873
+ type Unsupported = 2;
874
+ }
870
875
  /**
871
- * Create an email format error
872
- * @param options The optional validation error options
876
+ * An object that represents a location in the `FieldTree` tree structure and is used to bind logic to a
877
+ * particular part of the structure prior to the creation of the form. Because the `FieldPath`
878
+ * exists prior to the form's creation, it cannot be used to access any of the field state.
873
879
  *
874
- * @category validation
880
+ * @template TValue The type of the data which the form is wrapped around.
881
+ * @template TPathKind The kind of path (root field, child field, or item of an array)
882
+ *
883
+ * @category types
875
884
  * @experimental 21.0.0
876
885
  */
877
- declare function emailError(options?: ValidationErrorOptions): WithoutField<EmailValidationError>;
886
+ type SchemaPath<TValue, TSupportsRules extends SchemaPathRules = SchemaPathRules.Supported, TPathKind extends PathKind = PathKind.Root> = {
887
+ [ɵɵTYPE]: {
888
+ value: () => TValue;
889
+ supportsRules: TSupportsRules;
890
+ pathKind: TPathKind;
891
+ };
892
+ };
878
893
  /**
879
- * Create a standard schema issue error associated with the target field
880
- * @param issue The standard schema issue
881
- * @param options The validation error options
894
+ * Schema path used if the value is an AbstractControl.
882
895
  *
883
- * @category validation
896
+ * @category interop
884
897
  * @experimental 21.0.0
885
898
  */
886
- declare function standardSchemaError(issue: StandardSchemaV1.Issue, options: WithField<ValidationErrorOptions>): StandardSchemaValidationError;
899
+ type CompatSchemaPath<TControl extends AbstractControl, TPathKind extends PathKind = PathKind.Root> = SchemaPath<TControl extends AbstractControl<unknown, infer TValue> ? TValue : never, SchemaPathRules.Unsupported, TPathKind> & {
900
+ [ɵɵTYPE]: {
901
+ control: TControl;
902
+ };
903
+ };
887
904
  /**
888
- * Create a standard schema issue error
889
- * @param issue The standard schema issue
890
- * @param options The optional validation error options
905
+ * Nested schema path.
906
+ *
907
+ * It mirrors the structure of a given data structure, and allows applying rules to the appropriate
908
+ * fields.
891
909
  *
892
- * @category validation
893
910
  * @experimental 21.0.0
894
911
  */
895
- declare function standardSchemaError(issue: StandardSchemaV1.Issue, options?: ValidationErrorOptions): WithoutField<StandardSchemaValidationError>;
912
+ type SchemaPathTree<TModel, TPathKind extends PathKind = PathKind.Root> = ([TModel] extends [AbstractControl] ? CompatSchemaPath<TModel, TPathKind> : SchemaPath<TModel, SchemaPathRules.Supported, TPathKind>) & (TModel extends AbstractControl ? unknown : TModel extends Array<any> ? unknown : TModel extends Record<string, any> ? {
913
+ [K in keyof TModel]: MaybeSchemaPathTree<TModel[K], PathKind.Child>;
914
+ } : unknown);
896
915
  /**
897
- * Create a custom error associated with the target field
898
- * @param obj The object to create an error from
916
+ * Helper type for defining `FieldPath`. Given a type `TValue` that may include `undefined`, it
917
+ * extracts the `undefined` outside the `FieldPath` type.
918
+ *
919
+ * For example `MaybeFieldPath<{a: number} | undefined, PathKind.Child>` would be equivalent to
920
+ * `undefined | FieldTree<{a: number}, PathKind.child>`.
921
+ *
922
+ * @template TValue The type of the data which the field is wrapped around.
923
+ * @template TPathKind The kind of path (root field, child field, or item of an array)
899
924
  *
900
- * @category validation
901
925
  * @experimental 21.0.0
902
926
  */
903
- declare function customError<E extends Partial<ValidationError.WithField>>(obj: WithField<E>): CustomValidationError;
927
+ type MaybeSchemaPathTree<TModel, TPathKind extends PathKind = PathKind.Root> = (TModel & undefined) | SchemaPathTree<Exclude<TModel, undefined>, TPathKind>;
904
928
  /**
905
- * Create a custom error
906
- * @param obj The object to create an error from
929
+ * Defines logic for a form.
907
930
  *
908
- * @category validation
931
+ * @template TValue The type of data stored in the form that this schema is attached to.
932
+ *
933
+ * @category types
909
934
  * @experimental 21.0.0
910
935
  */
911
- declare function customError<E extends Partial<ValidationError.WithField>>(obj?: E): WithoutField<CustomValidationError>;
936
+ type Schema<in TModel> = {
937
+ [ɵɵTYPE]: SchemaFn<TModel, PathKind.Root>;
938
+ };
912
939
  /**
913
- * Common interface for all validation errors.
914
- *
915
- * This can be returned from validators.
940
+ * Function that defines rules for a schema.
916
941
  *
917
- * It's also used by the creation functions to create an instance
918
- * (e.g. `requiredError`, `minError`, etc.).
942
+ * @template TModel The type of data stored in the form that this schema function is attached to.
943
+ * @template TPathKind The kind of path this schema function can be bound to.
919
944
  *
920
- * @category validation
945
+ * @category types
921
946
  * @experimental 21.0.0
922
947
  */
923
- interface ValidationError {
924
- /** Identifies the kind of error. */
925
- readonly kind: string;
926
- /** Human readable error message. */
927
- readonly message?: string;
928
- }
929
- declare namespace ValidationError {
930
- /**
931
- * Validation error with a field.
932
- *
933
- * This is returned from field state, e.g., catField.errors() would be of a list of errors with
934
- * `field: catField` bound to state.
935
- */
936
- interface WithField extends ValidationError {
937
- /** The field associated with this error. */
938
- readonly field: FieldTree<unknown>;
939
- }
940
- /**
941
- * Validation error with optional field.
942
- *
943
- * This is generally used in places where the result might have a field.
944
- * e.g., as a result of a `validateTree`, or when handling form submission.
945
- */
946
- interface WithOptionalField extends ValidationError {
947
- /** The field associated with this error. */
948
- readonly field?: FieldTree<unknown>;
949
- }
950
- /**
951
- * Validation error with no field.
952
- *
953
- * This is used to strongly enforce that fields are not allowed in validation result.
954
- */
955
- interface WithoutField extends ValidationError {
956
- /** The field associated with this error. */
957
- readonly field?: never;
958
- }
959
- }
948
+ type SchemaFn<TModel, TPathKind extends PathKind = PathKind.Root> = (p: SchemaPathTree<TModel, TPathKind>) => void;
960
949
  /**
961
- * A custom error that may contain additional properties
950
+ * A schema or schema definition function.
962
951
  *
963
- * @category validation
952
+ * @template TModel The type of data stored in the form that this schema function is attached to.
953
+ * @template TPathKind The kind of path this schema function can be bound to.
954
+ *
955
+ * @category types
964
956
  * @experimental 21.0.0
965
957
  */
966
- declare class CustomValidationError implements ValidationError {
967
- /** Brand the class to avoid Typescript structural matching */
968
- private __brand;
969
- /**
970
- * Allow the user to attach arbitrary other properties.
971
- */
972
- [key: PropertyKey]: unknown;
973
- /** Identifies the kind of error. */
974
- readonly kind: string;
975
- /** The field associated with this error. */
976
- readonly field: FieldTree<unknown>;
977
- /** Human readable error message. */
978
- readonly message?: string;
979
- constructor(options?: ValidationErrorOptions);
980
- }
958
+ type SchemaOrSchemaFn<TModel, TPathKind extends PathKind = PathKind.Root> = Schema<TModel> | SchemaFn<TModel, TPathKind>;
981
959
  /**
982
- * Internal version of `NgValidationError`, we create this separately so we can change its type on
983
- * the exported version to a type union of the possible sub-classes.
960
+ * A function that receives the `FieldContext` for the field the logic is bound to and returns
961
+ * a specific result type.
962
+ *
963
+ * @template TValue The data type for the field the logic is bound to.
964
+ * @template TReturn The type of the result returned by the logic function.
965
+ * @template TPathKind The kind of path the logic is applied to (root field, child field, or item of an array)
984
966
  *
967
+ * @category types
985
968
  * @experimental 21.0.0
986
969
  */
987
- declare abstract class _NgValidationError implements ValidationError {
988
- /** Brand the class to avoid Typescript structural matching */
989
- private __brand;
990
- /** Identifies the kind of error. */
991
- readonly kind: string;
992
- /** The field associated with this error. */
993
- readonly field: FieldTree<unknown>;
994
- /** Human readable error message. */
995
- readonly message?: string;
996
- constructor(options?: ValidationErrorOptions);
997
- }
970
+ type LogicFn<TValue, TReturn, TPathKind extends PathKind = PathKind.Root> = (ctx: FieldContext<TValue, TPathKind>) => TReturn;
998
971
  /**
999
- * An error used to indicate that a required field is empty.
972
+ * A function that takes the `FieldContext` for the field being validated and returns a
973
+ * `ValidationResult` indicating errors for the field.
974
+ *
975
+ * @template TValue The type of value stored in the field being validated
976
+ * @template TPathKind The kind of path being validated (root field, child field, or item of an array)
1000
977
  *
1001
978
  * @category validation
1002
979
  * @experimental 21.0.0
1003
980
  */
1004
- declare class RequiredValidationError extends _NgValidationError {
1005
- readonly kind = "required";
1006
- }
981
+ type FieldValidator<TValue, TPathKind extends PathKind = PathKind.Root> = LogicFn<TValue, ValidationResult<ValidationError.WithoutField>, TPathKind>;
1007
982
  /**
1008
- * An error used to indicate that a value is lower than the minimum allowed.
983
+ * A function that takes the `FieldContext` for the field being validated and returns a
984
+ * `TreeValidationResult` indicating errors for the field and its sub-fields.
1009
985
  *
1010
- * @category validation
986
+ * @template TValue The type of value stored in the field being validated
987
+ * @template TPathKind The kind of path being validated (root field, child field, or item of an array)
988
+ *
989
+ * @category types
1011
990
  * @experimental 21.0.0
1012
991
  */
1013
- declare class MinValidationError extends _NgValidationError {
1014
- readonly min: number;
1015
- readonly kind = "min";
1016
- constructor(min: number, options?: ValidationErrorOptions);
1017
- }
992
+ type TreeValidator<TValue, TPathKind extends PathKind = PathKind.Root> = LogicFn<TValue, TreeValidationResult, TPathKind>;
1018
993
  /**
1019
- * An error used to indicate that a value is higher than the maximum allowed.
994
+ * A function that takes the `FieldContext` for the field being validated and returns a
995
+ * `ValidationResult` indicating errors for the field and its sub-fields. In a `Validator` all
996
+ * errors must explicitly define their target field.
1020
997
  *
1021
- * @category validation
998
+ * @template TValue The type of value stored in the field being validated
999
+ * @template TPathKind The kind of path being validated (root field, child field, or item of an array)
1000
+ *
1001
+ * @category types
1022
1002
  * @experimental 21.0.0
1023
1003
  */
1024
- declare class MaxValidationError extends _NgValidationError {
1025
- readonly max: number;
1026
- readonly kind = "max";
1027
- constructor(max: number, options?: ValidationErrorOptions);
1028
- }
1004
+ type Validator<TValue, TPathKind extends PathKind = PathKind.Root> = LogicFn<TValue, ValidationResult, TPathKind>;
1029
1005
  /**
1030
- * An error used to indicate that a value is shorter than the minimum allowed length.
1006
+ * Provides access to the state of the current field as well as functions that can be used to look
1007
+ * up state of other fields based on a `FieldPath`.
1031
1008
  *
1032
- * @category validation
1009
+ * @category types
1033
1010
  * @experimental 21.0.0
1034
1011
  */
1035
- declare class MinLengthValidationError extends _NgValidationError {
1036
- readonly minLength: number;
1037
- readonly kind = "minLength";
1038
- constructor(minLength: number, options?: ValidationErrorOptions);
1039
- }
1012
+ type FieldContext<TValue, TPathKind extends PathKind = PathKind.Root> = TPathKind extends PathKind.Item ? ItemFieldContext<TValue> : TPathKind extends PathKind.Child ? ChildFieldContext<TValue> : RootFieldContext<TValue>;
1040
1013
  /**
1041
- * An error used to indicate that a value is longer than the maximum allowed length.
1014
+ * The base field context that is available for all fields.
1042
1015
  *
1043
- * @category validation
1044
1016
  * @experimental 21.0.0
1045
1017
  */
1046
- declare class MaxLengthValidationError extends _NgValidationError {
1047
- readonly maxLength: number;
1048
- readonly kind = "maxLength";
1049
- constructor(maxLength: number, options?: ValidationErrorOptions);
1018
+ interface RootFieldContext<TValue> {
1019
+ /** A signal containing the value of the current field. */
1020
+ readonly value: Signal<TValue>;
1021
+ /** The state of the current field. */
1022
+ readonly state: FieldState<TValue>;
1023
+ /** The current field. */
1024
+ readonly field: FieldTree<TValue>;
1025
+ /** Gets the value of the field represented by the given path. */
1026
+ valueOf<PValue>(p: SchemaPath<PValue, SchemaPathRules>): PValue;
1027
+ /** Gets the state of the field represented by the given path. */
1028
+ stateOf<PControl extends AbstractControl>(p: CompatSchemaPath<PControl>): CompatFieldState<PControl>;
1029
+ stateOf<PValue>(p: SchemaPath<PValue, SchemaPathRules>): FieldState<PValue>;
1030
+ /** Gets the field represented by the given path. */
1031
+ fieldTreeOf<PModel>(p: SchemaPathTree<PModel>): FieldTree<PModel>;
1032
+ /** The list of keys that lead from the root field to the current field. */
1033
+ readonly pathKeys: Signal<readonly string[]>;
1050
1034
  }
1051
1035
  /**
1052
- * An error used to indicate that a value does not match the required pattern.
1036
+ * Field context that is available for all fields that are a child of another field.
1053
1037
  *
1054
- * @category validation
1038
+ * @category structure
1055
1039
  * @experimental 21.0.0
1056
1040
  */
1057
- declare class PatternValidationError extends _NgValidationError {
1058
- readonly pattern: RegExp;
1059
- readonly kind = "pattern";
1060
- constructor(pattern: RegExp, options?: ValidationErrorOptions);
1041
+ interface ChildFieldContext<TValue> extends RootFieldContext<TValue> {
1042
+ /** The key of the current field in its parent field. */
1043
+ readonly key: Signal<string>;
1061
1044
  }
1062
1045
  /**
1063
- * An error used to indicate that a value is not a valid email.
1046
+ * Field context that is available for all fields that are an item in an array field.
1064
1047
  *
1065
- * @category validation
1066
1048
  * @experimental 21.0.0
1067
1049
  */
1068
- declare class EmailValidationError extends _NgValidationError {
1069
- readonly kind = "email";
1050
+ interface ItemFieldContext<TValue> extends ChildFieldContext<TValue> {
1051
+ /** The index of the current field in its parent field. */
1052
+ readonly index: Signal<number>;
1070
1053
  }
1071
1054
  /**
1072
- * An error used to indicate an issue validating against a standard schema.
1055
+ * Gets the item type of an object that is possibly an array.
1073
1056
  *
1074
- * @category validation
1075
1057
  * @experimental 21.0.0
1076
1058
  */
1077
- declare class StandardSchemaValidationError extends _NgValidationError {
1078
- readonly issue: StandardSchemaV1.Issue;
1079
- readonly kind = "standardSchema";
1080
- constructor(issue: StandardSchemaV1.Issue, options?: ValidationErrorOptions);
1081
- }
1059
+ type ItemType<T extends Object> = T extends ReadonlyArray<any> ? T[number] : T[keyof T];
1082
1060
  /**
1083
- * The base class for all built-in, non-custom errors. This class can be used to check if an error
1084
- * is one of the standard kinds, allowing you to switch on the kind to further narrow the type.
1061
+ * A function that defines custom debounce logic for a field.
1085
1062
  *
1086
- * @example
1087
- * ```ts
1088
- * const f = form(...);
1089
- * for (const e of form().errors()) {
1090
- * if (e instanceof NgValidationError) {
1091
- * switch(e.kind) {
1092
- * case 'required':
1093
- * console.log('This is required!');
1094
- * break;
1095
- * case 'min':
1096
- * console.log(`Must be at least ${e.min}`);
1097
- * break;
1098
- * ...
1099
- * }
1100
- * }
1101
- * }
1102
- * ```
1063
+ * @param context The field context.
1064
+ * @param abortSignal An `AbortSignal` used to communicate that the debounced operation was aborted.
1065
+ * @returns A `Promise<void>` to debounce an update, or `void` to apply an update immediately.
1066
+ * @template TValue The type of value stored in the field.
1067
+ * @template TPathKind The kind of path the debouncer is applied to (root field, child field, or item of an array).
1103
1068
  *
1104
- * @category validation
1105
1069
  * @experimental 21.0.0
1106
1070
  */
1107
- declare const NgValidationError: abstract new () => NgValidationError;
1108
- type NgValidationError = RequiredValidationError | MinValidationError | MaxValidationError | MinLengthValidationError | MaxLengthValidationError | PatternValidationError | EmailValidationError | StandardSchemaValidationError;
1071
+ type Debouncer<TValue, TPathKind extends PathKind = PathKind.Root> = (context: FieldContext<TValue, TPathKind>, abortSignal: AbortSignal) => Promise<void> | void;
1109
1072
 
1110
1073
  /**
1111
1074
  * Configuration options for signal forms.
@@ -1242,27 +1205,41 @@ declare class LogicContainer {
1242
1205
  readonly syncTreeErrors: ArrayMergeIgnoreLogic<ValidationError.WithField, null>;
1243
1206
  /** Logic that produces asynchronous validation results (errors or 'pending'). */
1244
1207
  readonly asyncErrors: ArrayMergeIgnoreLogic<ValidationError.WithField | 'pending', null>;
1245
- /** A map of metadata keys to the `AbstractLogic` instances that compute their values. */
1246
- private readonly metadata;
1208
+ /** A map of aggregate metadata keys to the `AbstractLogic` instances that compute their values. */
1209
+ private readonly aggregateMetadataKeys;
1210
+ /** A map of metadata keys to the factory functions that create their values. */
1211
+ private readonly metadataFactories;
1247
1212
  /**
1248
1213
  * Constructs a new `Logic` container.
1249
1214
  * @param predicates An array of predicates that must all be true for the logic
1250
1215
  * functions within this container to be active.
1251
1216
  */
1252
1217
  constructor(predicates: ReadonlyArray<BoundPredicate>);
1253
- /** Checks whether there is logic for the given metadata key. */
1254
- hasMetadata(key: MetadataKey<any, any, any>): boolean;
1218
+ /** Checks whether there is logic for the given aggregate metadata key. */
1219
+ hasAggregateMetadata(key: AggregateMetadataKey<any, any>): boolean;
1220
+ /**
1221
+ * Gets an iterable of [aggregate metadata, logic function] pairs.
1222
+ * @returns An iterable of aggregate metadata entries.
1223
+ */
1224
+ getAggregateMetadataEntries(): MapIterator<[AggregateMetadataKey<unknown, unknown>, AbstractLogic<unknown, unknown>]>;
1255
1225
  /**
1256
- * Gets an iterable of [metadata key, logic function] pairs.
1257
- * @returns An iterable of metadata keys.
1226
+ * Gets an iterable of [metadata, value factory function] pairs.
1227
+ * @returns An iterable of metadata factory entries.
1258
1228
  */
1259
- getMetadataKeys(): MapIterator<MetadataKey<unknown, unknown, unknown>>;
1229
+ getMetadataFactoryEntries(): MapIterator<[MetadataKey<unknown>, (ctx: FieldContext<unknown>) => unknown]>;
1260
1230
  /**
1261
- * Retrieves or creates the `AbstractLogic` for a given metadata key.
1262
- * @param key The `MetadataKey` for which to get the logic.
1231
+ * Retrieves or creates the `AbstractLogic` for a given aggregate metadata key.
1232
+ * @param key The `AggregateMetadataKey` for which to get the logic.
1263
1233
  * @returns The `AbstractLogic` associated with the key.
1264
1234
  */
1265
- getMetadata<T>(key: MetadataKey<any, T, any>): AbstractLogic<T>;
1235
+ getAggregateMetadata<T>(key: AggregateMetadataKey<any, T>): AbstractLogic<T>;
1236
+ /**
1237
+ * Adds a factory function for a given metadata key.
1238
+ * @param key The `MetadataKey` to associate the factory with.
1239
+ * @param factory The factory function.
1240
+ * @throws If a factory is already defined for the given key.
1241
+ */
1242
+ addMetadataFactory(key: MetadataKey<unknown>, factory: (ctx: FieldContext<unknown>) => unknown): void;
1266
1243
  /**
1267
1244
  * Merges logic from another `Logic` instance into this one.
1268
1245
  * @param other The `Logic` instance to merge from.
@@ -1294,8 +1271,10 @@ declare abstract class AbstractLogicNodeBuilder {
1294
1271
  abstract addSyncTreeErrorRule(logic: LogicFn<any, ValidationResult>): void;
1295
1272
  /** Adds a rule for asynchronous validation errors for a field. */
1296
1273
  abstract addAsyncErrorRule(logic: LogicFn<any, AsyncValidationResult>): void;
1297
- /** Adds a rule to compute metadata for a field. */
1298
- abstract addMetadataRule<M>(key: MetadataKey<unknown, M, unknown>, logic: LogicFn<any, M>): void;
1274
+ /** Adds a rule to compute aggregate metadata for a field. */
1275
+ abstract addAggregateMetadataRule<M>(key: AggregateMetadataKey<unknown, M>, logic: LogicFn<any, M>): void;
1276
+ /** Adds a factory function to produce a data value associated with a field. */
1277
+ abstract addMetadataFactory<D>(key: MetadataKey<D>, factory: (ctx: FieldContext<any>) => D): void;
1299
1278
  /**
1300
1279
  * Gets a builder for a child node associated with the given property key.
1301
1280
  * @param key The property key of the child.
@@ -1341,7 +1320,8 @@ declare class LogicNodeBuilder extends AbstractLogicNodeBuilder {
1341
1320
  addSyncErrorRule(logic: LogicFn<any, ValidationResult<ValidationError.WithField>>): void;
1342
1321
  addSyncTreeErrorRule(logic: LogicFn<any, ValidationResult<ValidationError.WithField>>): void;
1343
1322
  addAsyncErrorRule(logic: LogicFn<any, AsyncValidationResult<ValidationError.WithField>>): void;
1344
- addMetadataRule<T>(key: MetadataKey<unknown, T, any>, logic: LogicFn<any, T>): void;
1323
+ addAggregateMetadataRule<T>(key: AggregateMetadataKey<any, T>, logic: LogicFn<any, T>): void;
1324
+ addMetadataFactory<D>(key: MetadataKey<D>, factory: (ctx: FieldContext<any>) => D): void;
1345
1325
  getChild(key: PropertyKey): LogicNodeBuilder;
1346
1326
  hasLogic(builder: AbstractLogicNodeBuilder): boolean;
1347
1327
  /**
@@ -1470,13 +1450,13 @@ declare class FieldPathNode {
1470
1450
  */
1471
1451
  declare class FieldMetadataState {
1472
1452
  private readonly node;
1473
- /** A map of all `MetadataKey` that have been defined for this field. */
1453
+ /** A map of all `MetadataKey` and `AggregateMetadataKey` that have been defined for this field. */
1474
1454
  private readonly metadata;
1475
1455
  constructor(node: FieldNode);
1476
- /** Gets the value of an `MetadataKey` for the field. */
1477
- get<T>(key: MetadataKey<T, unknown, unknown>): T | undefined;
1456
+ /** Gets the value of a `MetadataKey` or `AggregateMetadataKey` for the field. */
1457
+ get<T>(key: MetadataKey<T> | AggregateMetadataKey<T, unknown>): T | undefined | Signal<T>;
1478
1458
  /** Checks whether the current metadata state has the given metadata key. */
1479
- has(key: MetadataKey<any, any, any>): boolean;
1459
+ has(key: MetadataKey<any> | AggregateMetadataKey<any, any>): boolean;
1480
1460
  }
1481
1461
 
1482
1462
  /**
@@ -1715,7 +1695,6 @@ declare class FieldNode implements FieldState<unknown> {
1715
1695
  * Proxy to this node which allows navigation of the form graph below it.
1716
1696
  */
1717
1697
  readonly fieldProxy: FieldTree<any>;
1718
- private readonly pathNode;
1719
1698
  constructor(options: FieldNodeOptions);
1720
1699
  /**
1721
1700
  * The `AbortController` for the currently debounced sync, or `undefined` if there is none.
@@ -1744,14 +1723,16 @@ declare class FieldNode implements FieldState<unknown> {
1744
1723
  get fieldBindings(): Signal<readonly Field<unknown>[]>;
1745
1724
  get submitting(): Signal<boolean>;
1746
1725
  get name(): Signal<string>;
1726
+ private metadataOrUndefined;
1747
1727
  get max(): Signal<number | undefined> | undefined;
1748
1728
  get maxLength(): Signal<number | undefined> | undefined;
1749
1729
  get min(): Signal<number | undefined> | undefined;
1750
1730
  get minLength(): Signal<number | undefined> | undefined;
1751
1731
  get pattern(): Signal<readonly RegExp[]>;
1752
1732
  get required(): Signal<boolean>;
1753
- metadata<M>(key: MetadataKey<M, any, any>): M | undefined;
1754
- hasMetadata(key: MetadataKey<any, any, any>): boolean;
1733
+ metadata<M>(key: AggregateMetadataKey<M, any>): Signal<M>;
1734
+ metadata<M>(key: MetadataKey<M>): M | undefined;
1735
+ hasMetadata(key: MetadataKey<any> | AggregateMetadataKey<any, any>): boolean;
1755
1736
  /**
1756
1737
  * Marks this specific field as touched.
1757
1738
  */
@@ -1791,8 +1772,11 @@ declare class FieldNode implements FieldState<unknown> {
1791
1772
  * Creates a new root field node for a new form.
1792
1773
  */
1793
1774
  static newRoot<T>(fieldManager: FormFieldManager, value: WritableSignal<T>, pathNode: FieldPathNode, adapter: FieldAdapter): FieldNode;
1775
+ /**
1776
+ * Creates a child field node based on the given options.
1777
+ */
1778
+ private static newChild;
1794
1779
  createStructure(options: FieldNodeOptions): RootFieldNodeStructure | ChildFieldNodeStructure;
1795
- private newChild;
1796
1780
  }
1797
1781
  /**
1798
1782
  * Field node of a field that has children.
@@ -1814,16 +1798,12 @@ interface ParentFieldNode extends FieldNode {
1814
1798
  type TrackingKey = PropertyKey & {
1815
1799
  __brand: 'FieldIdentity';
1816
1800
  };
1817
- type ChildNodeCtor = (key: string, trackingKey: TrackingKey | undefined, isArray: boolean) => FieldNode;
1818
1801
  /** Structural component of a `FieldNode` which tracks its path, parent, and children. */
1819
1802
  declare abstract class FieldNodeStructure {
1820
- /**
1821
- * Computed map of child fields, based on the current value of this field.
1822
- *
1823
- * This structure reacts to `this.value` and produces a new `ChildrenData` when the
1824
- * value changes structurally (fields added/removed/moved).
1825
- */
1826
- protected abstract readonly childrenMap: Signal<ChildrenData | undefined>;
1803
+ /** The logic to apply to this field. */
1804
+ readonly logic: LogicNode;
1805
+ /** Computed map of child fields, based on the current value of this field. */
1806
+ abstract readonly childrenMap: Signal<Map<TrackingKey, FieldNode> | undefined>;
1827
1807
  /** The field's value. */
1828
1808
  abstract readonly value: WritableSignal<unknown>;
1829
1809
  /**
@@ -1839,60 +1819,33 @@ declare abstract class FieldNodeStructure {
1839
1819
  abstract readonly pathKeys: Signal<readonly string[]>;
1840
1820
  /** The parent field of this field. */
1841
1821
  abstract readonly parent: FieldNode | undefined;
1842
- readonly logic: LogicNode;
1843
- readonly node: FieldNode;
1844
- readonly createChildNode: ChildNodeCtor;
1845
1822
  /** Added to array elements for tracking purposes. */
1846
1823
  readonly identitySymbol: symbol;
1847
1824
  /** Lazily initialized injector. Do not access directly, access via `injector` getter instead. */
1848
1825
  private _injector;
1849
1826
  /** Lazily initialized injector. */
1850
1827
  get injector(): DestroyableInjector;
1851
- constructor(logic: LogicNode, node: FieldNode, createChildNode: ChildNodeCtor);
1828
+ constructor(
1829
+ /** The logic to apply to this field. */
1830
+ logic: LogicNode);
1852
1831
  /** Gets the child fields of this field. */
1853
1832
  children(): Iterable<FieldNode>;
1854
1833
  /** Retrieve a child `FieldNode` of this node by property key. */
1855
1834
  getChild(key: PropertyKey): FieldNode | undefined;
1856
- /**
1857
- * Perform a reduction over a field's children (if any) and return the result.
1858
- *
1859
- * Optionally, the reduction is short circuited based on the provided `shortCircuit` function.
1860
- */
1861
- reduceChildren<T>(initialValue: T, fn: (child: FieldNode, value: T) => T, shortCircuit?: (value: T) => boolean): T;
1862
1835
  /** Destroys the field when it is no longer needed. */
1863
1836
  destroy(): void;
1864
- /**
1865
- * Creates a keyInParent signal for a field node.
1866
- *
1867
- * For root nodes, returns ROOT_KEY_IN_PARENT which throws when accessed.
1868
- * For child nodes, creates a computed that tracks the field's current key in its parent,
1869
- * with special handling for tracked array elements.
1870
- *
1871
- * @param options The field node options
1872
- * @param identityInParent The tracking identity (only for tracked array children)
1873
- * @param initialKeyInParent The initial key in parent (only for child nodes)
1874
- * @returns A signal representing the field's key in its parent
1875
- */
1876
- protected createKeyInParent(options: FieldNodeOptions, identityInParent: TrackingKey | undefined, initialKeyInParent: string | undefined): Signal<string>;
1877
- protected createChildrenMap(): Signal<ChildrenData | undefined>;
1878
- /**
1879
- * Creates a "reader" computed for the given key.
1880
- *
1881
- * A reader is a computed signal that memoizes the access of the `FieldNode` stored at this key
1882
- * (or returns `undefined` if no such field exists). Accessing fields via the reader ensures that
1883
- * reactive consumers aren't notified unless the field at a key actually changes.
1884
- */
1885
- private createReader;
1886
1837
  }
1887
1838
  /** The structural component of a `FieldNode` that is the root of its field tree. */
1888
1839
  declare class RootFieldNodeStructure extends FieldNodeStructure {
1840
+ /** The full field node that corresponds to this structure. */
1841
+ private readonly node;
1889
1842
  readonly fieldManager: FormFieldManager;
1890
1843
  readonly value: WritableSignal<unknown>;
1891
1844
  get parent(): undefined;
1892
1845
  get root(): FieldNode;
1893
1846
  get pathKeys(): Signal<readonly string[]>;
1894
1847
  get keyInParent(): Signal<string>;
1895
- protected readonly childrenMap: Signal<ChildrenData | undefined>;
1848
+ readonly childrenMap: Signal<Map<TrackingKey, FieldNode> | undefined>;
1896
1849
  /**
1897
1850
  * Creates the structure for the root node of a field tree.
1898
1851
  *
@@ -1906,17 +1859,16 @@ declare class RootFieldNodeStructure extends FieldNodeStructure {
1906
1859
  */
1907
1860
  constructor(
1908
1861
  /** The full field node that corresponds to this structure. */
1909
- node: FieldNode, logic: LogicNode, fieldManager: FormFieldManager, value: WritableSignal<unknown>, createChildNode: ChildNodeCtor);
1862
+ node: FieldNode, pathNode: FieldPathNode, logic: LogicNode, fieldManager: FormFieldManager, value: WritableSignal<unknown>, adapter: FieldAdapter, createChildNode: (options: ChildFieldNodeOptions) => FieldNode);
1910
1863
  }
1911
1864
  /** The structural component of a child `FieldNode` within a field tree. */
1912
1865
  declare class ChildFieldNodeStructure extends FieldNodeStructure {
1913
- readonly logic: LogicNode;
1914
1866
  readonly parent: ParentFieldNode;
1915
1867
  readonly root: FieldNode;
1916
1868
  readonly pathKeys: Signal<readonly string[]>;
1917
1869
  readonly keyInParent: Signal<string>;
1918
1870
  readonly value: WritableSignal<unknown>;
1919
- readonly childrenMap: Signal<ChildrenData | undefined>;
1871
+ readonly childrenMap: Signal<Map<TrackingKey, FieldNode> | undefined>;
1920
1872
  get fieldManager(): FormFieldManager;
1921
1873
  /**
1922
1874
  * Creates the structure for a child field node in a field tree.
@@ -1930,7 +1882,7 @@ declare class ChildFieldNodeStructure extends FieldNodeStructure {
1930
1882
  * @param adapter Adapter that knows how to create new fields and appropriate state.
1931
1883
  * @param createChildNode A factory function to create child nodes for this field.
1932
1884
  */
1933
- constructor(node: FieldNode, logic: LogicNode, parent: ParentFieldNode, identityInParent: TrackingKey | undefined, initialKeyInParent: string, createChildNode: ChildNodeCtor);
1885
+ constructor(node: FieldNode, pathNode: FieldPathNode, logic: LogicNode, parent: ParentFieldNode, identityInParent: TrackingKey | undefined, initialKeyInParent: string, adapter: FieldAdapter, createChildNode: (options: ChildFieldNodeOptions) => FieldNode);
1934
1886
  }
1935
1887
  /** Options passed when constructing a root field node. */
1936
1888
  interface RootFieldNodeOptions {
@@ -1966,38 +1918,6 @@ interface ChildFieldNodeOptions {
1966
1918
  }
1967
1919
  /** Options passed when constructing a field node. */
1968
1920
  type FieldNodeOptions = RootFieldNodeOptions | ChildFieldNodeOptions;
1969
- /**
1970
- * Derived data regarding child fields for a specific parent field.
1971
- */
1972
- interface ChildrenData {
1973
- /**
1974
- * Tracks `ChildData` for each property key within the parent.
1975
- */
1976
- readonly byPropertyKey: ReadonlyMap<string, ChildData>;
1977
- /**
1978
- * Tracks the instance of child `FieldNode`s by their tracking key, which is always 1:1 with the
1979
- * fields, even if they move around in the parent.
1980
- */
1981
- readonly byTrackingKey?: ReadonlyMap<TrackingKey, FieldNode>;
1982
- }
1983
- /**
1984
- * Data for a specific child within a parent.
1985
- */
1986
- interface ChildData {
1987
- /**
1988
- * A computed signal to access the `FieldNode` currently stored at a specific key.
1989
- *
1990
- * Because this is a computed, it only updates whenever the `FieldNode` at that key changes.
1991
- * Because `ChildData` is always associated with a specific key via `ChildrenData.byPropertyKey`,
1992
- * this computed gives a stable way to watch the field stored for a given property and only
1993
- * receives notifications when that field changes.
1994
- */
1995
- readonly reader: Signal<FieldNode | undefined>;
1996
- /**
1997
- * The child `FieldNode` currently stored at this key.
1998
- */
1999
- node: FieldNode;
2000
- }
2001
1921
 
2002
1922
  /**
2003
1923
  * Manages the collection of fields associated with a given `form`.
@@ -2344,5 +2264,5 @@ declare function submit<TModel>(form: FieldTree<TModel>, action: (form: FieldTre
2344
2264
  */
2345
2265
  declare function schema<TValue>(fn: SchemaFn<TValue>): Schema<TValue>;
2346
2266
 
2347
- export { CustomValidationError, EmailValidationError, FIELD, Field, MAX, MAX_LENGTH, MIN, MIN_LENGTH, MaxLengthValidationError, MaxValidationError, MetadataKey, MetadataReducer, MinLengthValidationError, MinValidationError, NgValidationError, PATTERN, PathKind, PatternValidationError, REQUIRED, RequiredValidationError, SchemaPathRules, StandardSchemaValidationError, ValidationError, apply, applyEach, applyWhen, applyWhenValue, createManagedMetadataKey, createMetadataKey, customError, emailError, form, maxError, maxLengthError, metadata, minError, minLengthError, patternError, provideSignalFormsConfig, requiredError, schema, standardSchemaError, submit };
2348
- export type { AsyncValidationResult, ChildFieldContext, CompatFieldState, CompatSchemaPath, Debouncer, DisabledReason, FieldContext, FieldState, FieldTree, FieldValidator, FormOptions, ItemFieldContext, ItemType, LogicFn, MaybeFieldTree, MaybeSchemaPathTree, MetadataSetterType, OneOrMany, ReadonlyArrayLike, RootFieldContext, Schema, SchemaFn, SchemaOrSchemaFn, SchemaPath, SchemaPathTree, SignalFormsConfig, Subfields, SubmittedStatus, TreeValidationResult, TreeValidator, ValidationResult, ValidationSuccess, Validator, WithField, WithOptionalField, WithoutField };
2267
+ export { AggregateMetadataKey, CustomValidationError, EmailValidationError, FIELD, Field, MAX, MAX_LENGTH, MIN, MIN_LENGTH, MaxLengthValidationError, MaxValidationError, MetadataKey, MinLengthValidationError, MinValidationError, NgValidationError, PATTERN, PathKind, PatternValidationError, REQUIRED, RequiredValidationError, SchemaPathRules, StandardSchemaValidationError, ValidationError, andMetadataKey, apply, applyEach, applyWhen, applyWhenValue, createMetadataKey, customError, emailError, form, listMetadataKey, maxError, maxLengthError, maxMetadataKey, minError, minLengthError, minMetadataKey, orMetadataKey, patternError, provideSignalFormsConfig, reducedMetadataKey, requiredError, schema, standardSchemaError, submit };
2268
+ export type { AsyncValidationResult, ChildFieldContext, CompatFieldState, CompatSchemaPath, Debouncer, DisabledReason, FieldContext, FieldState, FieldTree, FieldValidator, FormOptions, ItemFieldContext, ItemType, LogicFn, MaybeFieldTree, MaybeSchemaPathTree, OneOrMany, ReadonlyArrayLike, RootFieldContext, Schema, SchemaFn, SchemaOrSchemaFn, SchemaPath, SchemaPathTree, SignalFormsConfig, Subfields, SubmittedStatus, TreeValidationResult, TreeValidator, ValidationResult, ValidationSuccess, Validator, WithField, WithOptionalField, WithoutField };