@angular/forms 22.0.0-next.1 → 22.0.0-next.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@angular/forms",
3
- "version": "22.0.0-next.1",
3
+ "version": "22.0.0-next.2",
4
4
  "description": "Angular - directives and services for creating forms",
5
5
  "author": "angular",
6
6
  "license": "MIT",
@@ -12,9 +12,9 @@
12
12
  "@standard-schema/spec": "^1.0.0"
13
13
  },
14
14
  "peerDependencies": {
15
- "@angular/core": "22.0.0-next.1",
16
- "@angular/common": "22.0.0-next.1",
17
- "@angular/platform-browser": "22.0.0-next.1",
15
+ "@angular/core": "22.0.0-next.2",
16
+ "@angular/common": "22.0.0-next.2",
17
+ "@angular/platform-browser": "22.0.0-next.2",
18
18
  "rxjs": "^6.5.3 || ^7.4.0"
19
19
  },
20
20
  "repository": {
Binary file
@@ -1,11 +1,11 @@
1
1
  /**
2
- * @license Angular v22.0.0-next.1
2
+ * @license Angular v22.0.0-next.2
3
3
  * (c) 2010-2026 Google LLC. https://angular.dev/
4
4
  * License: MIT
5
5
  */
6
6
 
7
7
  import * as i0 from '@angular/core';
8
- import { WritableSignal, Signal, InjectionToken, Injector, Provider } from '@angular/core';
8
+ import { Signal, WritableSignal, Injector, InjectionToken, Provider } from '@angular/core';
9
9
  import { AbstractControl, ValidationErrors, FormControlStatus, ControlValueAccessor, ValidatorFn } from '@angular/forms';
10
10
  import { StandardSchemaV1 } from '@standard-schema/spec';
11
11
 
@@ -16,7 +16,7 @@ declare const ɵɵTYPE: unique symbol;
16
16
  /**
17
17
  * Options that can be specified when submitting a form.
18
18
  *
19
- * @experimental 21.2.0
19
+ * @experimental 21.2
20
20
  */
21
21
  interface FormSubmitOptions<TRootModel, TSubmittedModel> {
22
22
  /**
@@ -57,13 +57,13 @@ interface FormSubmitOptions<TRootModel, TSubmittedModel> {
57
57
  * A type that represents either a single value of type `T` or a readonly array of `T`.
58
58
  * @template T The type of the value(s).
59
59
  *
60
- * @experimental 21.0.0
60
+ * @experimental 21.0
61
61
  */
62
62
  type OneOrMany<T> = T | readonly T[];
63
63
  /**
64
64
  * The kind of `FieldPath` (`Root`, `Child` of another `FieldPath`, or `Item` in a `FieldPath` array)
65
65
  *
66
- * @experimental 21.0.0
66
+ * @experimental 21.0
67
67
  */
68
68
  type PathKind = PathKind.Root | PathKind.Child | PathKind.Item;
69
69
  declare namespace PathKind {
@@ -95,11 +95,11 @@ declare namespace PathKind {
95
95
  * A reason for a field's disablement.
96
96
  *
97
97
  * @category logic
98
- * @experimental 21.0.0
98
+ * @experimental 21.0
99
99
  */
100
100
  interface DisabledReason {
101
101
  /** The field that is disabled. */
102
- readonly fieldTree: FieldTree<unknown>;
102
+ readonly fieldTree: ReadonlyFieldTree<unknown>;
103
103
  /** A user-facing message describing the reason for the disablement. */
104
104
  readonly message?: string;
105
105
  }
@@ -107,7 +107,7 @@ interface DisabledReason {
107
107
  * The absence of an error which indicates a successful validation result.
108
108
  *
109
109
  * @category types
110
- * @experimental 21.0.0
110
+ * @experimental 21.0
111
111
  */
112
112
  type ValidationSuccess = null | undefined | void;
113
113
  /**
@@ -122,7 +122,7 @@ type ValidationSuccess = null | undefined | void;
122
122
  * @template E the type of error (defaults to {@link ValidationError}).
123
123
  *
124
124
  * @category types
125
- * @experimental 21.0.0
125
+ * @experimental 21.0
126
126
  */
127
127
  type TreeValidationResult<E extends ValidationError.WithOptionalFieldTree = ValidationError.WithOptionalFieldTree> = ValidationSuccess | OneOrMany<E>;
128
128
  /**
@@ -136,7 +136,7 @@ type TreeValidationResult<E extends ValidationError.WithOptionalFieldTree = Vali
136
136
  * @template E the type of error (defaults to {@link ValidationError}).
137
137
  *
138
138
  * @category types
139
- * @experimental 21.0.0
139
+ * @experimental 21.0
140
140
  */
141
141
  type ValidationResult<E extends ValidationError = ValidationError> = ValidationSuccess | OneOrMany<E>;
142
142
  /**
@@ -149,7 +149,7 @@ type ValidationResult<E extends ValidationError = ValidationError> = ValidationS
149
149
  * @template E the type of error (defaults to {@link ValidationError}).
150
150
  *
151
151
  * @category types
152
- * @experimental 21.0.0
152
+ * @experimental 21.0
153
153
  */
154
154
  type AsyncValidationResult<E extends ValidationError = ValidationError> = ValidationResult<E> | 'pending';
155
155
  /**
@@ -159,68 +159,81 @@ type AsyncValidationResult<E extends ValidationError = ValidationError> = Valida
159
159
  * @template TKey The type of the property key which this field resides under in its parent.
160
160
  *
161
161
  * @category types
162
- * @experimental 21.2.0
162
+ * @experimental 21.2
163
163
  */
164
164
  type Field<TValue, TKey extends string | number = string | number> = () => FieldState<TValue, TKey>;
165
165
  /**
166
166
  * An object that represents a tree of fields in a form. This includes both primitive value fields
167
167
  * (e.g. fields that contain a `string` or `number`), as well as "grouping fields" that contain
168
- * sub-fields. `FieldTree` objects are arranged in a tree whose structure mimics the structure of the
169
- * underlying data. For example a `FieldTree<{x: number}>` has a property `x` which contains a
168
+ * sub-fields. `FieldTree` objects are arranged in a tree whose structure mimics the structure of
169
+ * the underlying data. For example a `FieldTree<{x: number}>` has a property `x` which contains a
170
170
  * `FieldTree<number>`. To access the state associated with a field, call it as a function.
171
171
  *
172
172
  * @template TValue The type of the data which the field is wrapped around.
173
173
  * @template TKey The type of the property key which this field resides under in its parent.
174
+ * @template TMode Determines whether the field state is readonly or writable. Defaults to writable.
175
+ * For readonly, use {@link ReadonlyFieldTree}.
174
176
  *
175
177
  * @category types
176
- * @experimental 21.0.0
178
+ * @experimental 21.0
179
+ */
180
+ type FieldTree<TModel, TKey extends string | number = string | number, TMode extends 'writable' | 'readonly' = 'writable'> = (() => [TModel] extends [AbstractControl] ? CompatFieldState<TModel, TKey, TMode> : FieldStateByMode<TModel, TKey, TMode>) & ([TModel] extends [AbstractControl] ? object : [TModel] extends [ReadonlyArray<infer U>] ? ReadonlyArrayLike<MaybeFieldTree<U, number, TMode>> : TModel extends Record<string, any> ? Subfields<TModel, TMode> : object);
181
+ /**
182
+ * A readonly {@link FieldTree}.
183
+ *
184
+ * @category types
185
+ * @experimental 22.0
177
186
  */
178
- type FieldTree<TModel, TKey extends string | number = string | number> = (() => [TModel] extends [AbstractControl] ? CompatFieldState<TModel, TKey> : FieldState<TModel, TKey>) & ([TModel] extends [AbstractControl] ? object : [TModel] extends [ReadonlyArray<infer U>] ? ReadonlyArrayLike<MaybeFieldTree<U, number>> : TModel extends Record<string, any> ? Subfields<TModel> : object);
187
+ type ReadonlyFieldTree<TModel, TKey extends string | number = string | number> = FieldTree<TModel, TKey, 'readonly'>;
179
188
  /**
180
189
  * The sub-fields that a user can navigate to from a `FieldTree<TModel>`.
181
190
  *
182
191
  * @template TModel The type of the data which the parent field is wrapped around.
192
+ * @template TMode Determines whether the field state is readonly or writable.
183
193
  *
184
- * @experimental 21.0.0
194
+ * @experimental 21.0
185
195
  */
186
- type Subfields<TModel> = {
187
- readonly [K in keyof TModel as TModel[K] extends Function ? never : K]: MaybeFieldTree<TModel[K], string>;
196
+ type Subfields<TModel, TMode extends 'writable' | 'readonly' = 'writable'> = {
197
+ readonly [K in keyof TModel as TModel[K] extends Function ? never : K]: MaybeFieldTree<TModel[K], string, TMode>;
188
198
  } & {
189
- [Symbol.iterator](): Iterator<[string, MaybeFieldTree<TModel[keyof TModel], string>]>;
199
+ [Symbol.iterator](): Iterator<[string, MaybeFieldTree<TModel[keyof TModel], string, TMode>]>;
190
200
  };
191
201
  /**
192
202
  * An iterable object with the same shape as a readonly array.
193
203
  *
194
204
  * @template T The array item type.
195
205
  *
196
- * @experimental 21.0.0
206
+ * @experimental 21.0
197
207
  */
198
208
  type ReadonlyArrayLike<T> = Pick<ReadonlyArray<T>, number | 'length' | typeof Symbol.iterator>;
199
209
  /**
200
- * Helper type for defining `FieldTree`. Given a type `TValue` that may include `undefined`, it extracts
201
- * the `undefined` outside the `FieldTree` type.
210
+ * Helper type for defining `FieldTree`. Given a type `TValue` that may include `undefined`,
211
+ * it extracts the `undefined` outside the `FieldTree` type.
202
212
  *
203
- * For example `MaybeField<{a: number} | undefined, TKey>` would be equivalent to
213
+ * For example `MaybeFieldTree<{a: number} | undefined, TKey>` would be equivalent to
204
214
  * `undefined | FieldTree<{a: number}, TKey>`.
205
215
  *
206
216
  * @template TModel The type of the data which the field is wrapped around.
207
217
  * @template TKey The type of the property key which this field resides under in its parent.
218
+ * @template TMode Determines whether the field state is readonly or writable.
208
219
  *
209
- * @experimental 21.0.0
220
+ * @experimental 22.0
210
221
  */
211
- type MaybeFieldTree<TModel, TKey extends string | number = string | number> = (TModel & undefined) | FieldTree<Exclude<TModel, undefined>, TKey>;
222
+ type MaybeFieldTree<TModel, TKey extends string | number = string | number, TMode extends 'writable' | 'readonly' = 'writable'> = (TModel & undefined) | FieldTree<Exclude<TModel, undefined>, TKey, TMode>;
212
223
  /**
213
- * Contains all of the state (e.g. value, statuses, etc.) associated with a `FieldTree`, exposed as
214
- * signals.
224
+ * A readonly view of a {@link FieldTree}'s state.
225
+ *
226
+ * @template TValue The type of the data which the field is wrapped around.
227
+ * @template TKey The type of the property key which this field resides under in its parent.
215
228
  *
216
229
  * @category structure
217
- * @experimental 21.0.0
230
+ * @experimental 22.0
218
231
  */
219
- interface FieldState<TValue, TKey extends string | number = string | number> {
232
+ interface ReadonlyFieldState<TValue, TKey extends string | number = string | number> {
220
233
  /**
221
234
  * The {@link FieldTree} associated with this field state.
222
235
  */
223
- readonly fieldTree: FieldTree<unknown, TKey>;
236
+ readonly fieldTree: ReadonlyFieldTree<unknown, TKey>;
224
237
  /**
225
238
  * A writable signal containing the value for this field.
226
239
  *
@@ -229,7 +242,15 @@ interface FieldState<TValue, TKey extends string | number = string | number> {
229
242
  * While updates from the UI control are eventually reflected here, they may be delayed if
230
243
  * debounced.
231
244
  */
232
- readonly value: WritableSignal<TValue>;
245
+ readonly value: Signal<TValue>;
246
+ /**
247
+ * A signal containing the value of the control to which this field is bound.
248
+ *
249
+ * This differs from {@link value} in that it's not subject to debouncing, and thus is used to
250
+ * buffer debounced updates from the control to the field. This will also not take into account
251
+ * the {@link controlValue} of children.
252
+ */
253
+ readonly controlValue: Signal<TValue>;
233
254
  /**
234
255
  * A signal indicating whether the field is currently disabled.
235
256
  */
@@ -341,7 +362,47 @@ interface FieldState<TValue, TKey extends string | number = string | number> {
341
362
  /**
342
363
  * The {@link FormField} directives that bind this field to a UI control.
343
364
  */
344
- readonly formFieldBindings: Signal<readonly FormField<unknown>[]>;
365
+ readonly formFieldBindings: Signal<readonly FormFieldBinding[]>;
366
+ /**
367
+ * Reads a metadata value from the field.
368
+ * @param key The metadata key to read.
369
+ */
370
+ metadata<M>(key: MetadataKey<M, any, any>): M | undefined;
371
+ /**
372
+ * Checks whether a metadata value exists on the field.
373
+ * @param key The metadata key to check.
374
+ */
375
+ hasMetadata(key: MetadataKey<any, any, any>): boolean;
376
+ /**
377
+ * Focuses the first UI control in the DOM that is bound to this field state.
378
+ * If no UI control is bound, does nothing.
379
+ * @param options Optional focus options to pass to the native focus() method.
380
+ */
381
+ focusBoundControl(options?: FocusOptions): void;
382
+ }
383
+ /**
384
+ * A writable view of a {@link FieldTree}'s state.
385
+ *
386
+ * @template TValue The type of the data which the field is wrapped around.
387
+ * @template TKey The type of the property key which this field resides under in its parent.
388
+ *
389
+ * @category structure
390
+ * @experimental 21.0
391
+ */
392
+ interface FieldState<TValue, TKey extends string | number = string | number> extends ReadonlyFieldState<TValue, TKey> {
393
+ /**
394
+ * The {@link FieldTree} associated with this field state.
395
+ */
396
+ readonly fieldTree: FieldTree<unknown, TKey>;
397
+ /**
398
+ * A writable signal containing the value for this field.
399
+ *
400
+ * Updating this signal will update the data model that the field is bound to.
401
+ *
402
+ * While updates from the UI control are eventually reflected here, they may be delayed if
403
+ * debounced.
404
+ */
405
+ readonly value: WritableSignal<TValue>;
345
406
  /**
346
407
  * A signal containing the value of the control to which this field is bound.
347
408
  *
@@ -358,11 +419,6 @@ interface FieldState<TValue, TKey extends string | number = string | number> {
358
419
  * Sets the touched status of the field to `true`.
359
420
  */
360
421
  markAsTouched(): void;
361
- /**
362
- * Reads a metadata value from the field.
363
- * @param key The metadata key to read.
364
- */
365
- metadata<M>(key: MetadataKey<M, any, any>): M | undefined;
366
422
  /**
367
423
  * Resets the {@link touched} and {@link dirty} state of the field and its descendants.
368
424
  *
@@ -371,26 +427,62 @@ interface FieldState<TValue, TKey extends string | number = string | number> {
371
427
  * @param value Optional value to set to the form. If not passed, the value will not be changed.
372
428
  */
373
429
  reset(value?: TValue): void;
374
- /**
375
- * Focuses the first UI control in the DOM that is bound to this field state.
376
- * If no UI control is bound, does nothing.
377
- * @param options Optional focus options to pass to the native focus() method.
378
- */
379
- focusBoundControl(options?: FocusOptions): void;
380
430
  }
381
431
  /**
382
432
  * This is FieldState also providing access to the wrapped FormControl.
383
433
  *
384
434
  * @category interop
385
- * @experimental 21.0.0
435
+ * @experimental 21.0
386
436
  */
387
- type CompatFieldState<TControl extends AbstractControl, TKey extends string | number = string | number> = FieldState<TControl extends AbstractControl<unknown, infer TValue> ? TValue : never, TKey> & {
437
+ type CompatFieldState<TControl extends AbstractControl, TKey extends string | number = string | number, TMode extends 'writable' | 'readonly' = 'writable'> = FieldStateByMode<TControl extends AbstractControl<unknown, infer TValue> ? TValue : never, TKey, TMode> & {
388
438
  control: Signal<TControl>;
389
439
  };
440
+ /**
441
+ * A readonly {@link CompatFieldState}.
442
+ *
443
+ * @category interop
444
+ * @experimental 22.0
445
+ */
446
+ type ReadonlyCompatFieldState<TControl extends AbstractControl, TKey extends string | number = string | number> = CompatFieldState<TControl, TKey, 'readonly'>;
447
+ /**
448
+ * Helper type that resolves to either a {@link FieldState} or {@link ReadonlyFieldState} based on
449
+ * the access mode.
450
+ *
451
+ * @template TValue The type of the value stored in the field.
452
+ * @template TKey The type of the property key.
453
+ * @template TMode The access mode ('readonly' or 'writable').
454
+ */
455
+ type FieldStateByMode<TValue, TKey extends string | number, TMode extends 'writable' | 'readonly'> = TMode extends 'writable' ? FieldState<TValue, TKey> : ReadonlyFieldState<TValue, TKey>;
456
+ /**
457
+ * Represents a binding between a field and a UI control through a {@link FormField} directive.
458
+ *
459
+ * @experimental 22.0
460
+ */
461
+ interface FormFieldBinding {
462
+ /**
463
+ * The HTML element on which the {@link FormField} directive is applied.
464
+ */
465
+ readonly element: HTMLElement;
466
+ /**
467
+ * The node injector for the element hosting this field binding.
468
+ */
469
+ readonly injector: Injector;
470
+ /**
471
+ * The {@link FieldState} of the field bound to the {@link FormField} directive.
472
+ */
473
+ readonly state: Signal<ReadonlyFieldState<unknown>>;
474
+ /**
475
+ * Focuses this field binding.
476
+ *
477
+ * By default, this will focus {@link element}. However, custom controls can implement their own
478
+ * focus behavior.
479
+ */
480
+ focus(options?: FocusOptions): void;
481
+ }
390
482
  /**
391
483
  * Allows declaring whether the Rules are supported for a given path.
392
484
  *
393
- * @experimental 21.0.0
485
+ * @experimental 21.0
394
486
  **/
395
487
  type SchemaPathRules = SchemaPathRules.Supported | SchemaPathRules.Unsupported;
396
488
  declare namespace SchemaPathRules {
@@ -412,7 +504,7 @@ declare namespace SchemaPathRules {
412
504
  * @template TPathKind The kind of path (root field, child field, or item of an array)
413
505
  *
414
506
  * @category types
415
- * @experimental 21.0.0
507
+ * @experimental 21.0
416
508
  */
417
509
  type SchemaPath<TValue, TSupportsRules extends SchemaPathRules = SchemaPathRules.Supported, TPathKind extends PathKind = PathKind.Root> = {
418
510
  [ɵɵTYPE]: {
@@ -425,7 +517,7 @@ type SchemaPath<TValue, TSupportsRules extends SchemaPathRules = SchemaPathRules
425
517
  * Schema path used if the value is an AbstractControl.
426
518
  *
427
519
  * @category interop
428
- * @experimental 21.0.0
520
+ * @experimental 21.0
429
521
  */
430
522
  type CompatSchemaPath<TControl extends AbstractControl, TPathKind extends PathKind = PathKind.Root> = SchemaPath<TControl extends AbstractControl<unknown, infer TValue> ? TValue : never, SchemaPathRules.Unsupported, TPathKind> & {
431
523
  [ɵɵTYPE]: {
@@ -438,7 +530,7 @@ type CompatSchemaPath<TControl extends AbstractControl, TPathKind extends PathKi
438
530
  * It mirrors the structure of a given data structure, and allows applying rules to the appropriate
439
531
  * fields.
440
532
  *
441
- * @experimental 21.0.0
533
+ * @experimental 21.0
442
534
  */
443
535
  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 ReadonlyArray<any> ? unknown : TModel extends Record<string, any> ? {
444
536
  [K in keyof TModel]: MaybeSchemaPathTree<TModel[K], PathKind.Child>;
@@ -453,7 +545,7 @@ type SchemaPathTree<TModel, TPathKind extends PathKind = PathKind.Root> = ([TMod
453
545
  * @template TValue The type of the data which the field is wrapped around.
454
546
  * @template TPathKind The kind of path (root field, child field, or item of an array)
455
547
  *
456
- * @experimental 21.0.0
548
+ * @experimental 21.0
457
549
  */
458
550
  type MaybeSchemaPathTree<TModel, TPathKind extends PathKind = PathKind.Root> = (TModel & undefined) | SchemaPathTree<Exclude<TModel, undefined>, TPathKind>;
459
551
  /**
@@ -495,7 +587,7 @@ type MaybeSchemaPathTree<TModel, TPathKind extends PathKind = PathKind.Root> = (
495
587
  * @template TModel Data type.
496
588
  *
497
589
  * @category types
498
- * @experimental 21.0.0
590
+ * @experimental 21.0
499
591
  */
500
592
  type Schema<in TModel> = {
501
593
  [ɵɵTYPE]: SchemaFn<TModel, PathKind.Root>;
@@ -519,7 +611,7 @@ type Schema<in TModel> = {
519
611
  * @template TPathKind The kind of path this schema function can be bound to.
520
612
  *
521
613
  * @category types
522
- * @experimental 21.0.0
614
+ * @experimental 21.0
523
615
  */
524
616
  type SchemaFn<TModel, TPathKind extends PathKind = PathKind.Root> = (p: SchemaPathTree<TModel, TPathKind>) => void;
525
617
  /**
@@ -529,7 +621,7 @@ type SchemaFn<TModel, TPathKind extends PathKind = PathKind.Root> = (p: SchemaPa
529
621
  * @template TPathKind The kind of path this schema function can be bound to.
530
622
  *
531
623
  * @category types
532
- * @experimental 21.0.0
624
+ * @experimental 21.0
533
625
  */
534
626
  type SchemaOrSchemaFn<TModel, TPathKind extends PathKind = PathKind.Root> = Schema<TModel> | SchemaFn<TModel, TPathKind>;
535
627
  /**
@@ -541,7 +633,7 @@ type SchemaOrSchemaFn<TModel, TPathKind extends PathKind = PathKind.Root> = Sche
541
633
  * @template TPathKind The kind of path the logic is applied to (root field, child field, or item of an array)
542
634
  *
543
635
  * @category types
544
- * @experimental 21.0.0
636
+ * @experimental 21.0
545
637
  */
546
638
  type LogicFn<TValue, TReturn, TPathKind extends PathKind = PathKind.Root> = (ctx: FieldContext<TValue, TPathKind>) => TReturn;
547
639
  /**
@@ -552,7 +644,7 @@ type LogicFn<TValue, TReturn, TPathKind extends PathKind = PathKind.Root> = (ctx
552
644
  * @template TPathKind The kind of path being validated (root field, child field, or item of an array)
553
645
  *
554
646
  * @category validation
555
- * @experimental 21.0.0
647
+ * @experimental 21.0
556
648
  */
557
649
  type FieldValidator<TValue, TPathKind extends PathKind = PathKind.Root> = LogicFn<TValue, ValidationResult<ValidationError.WithoutFieldTree>, TPathKind>;
558
650
  /**
@@ -563,7 +655,7 @@ type FieldValidator<TValue, TPathKind extends PathKind = PathKind.Root> = LogicF
563
655
  * @template TPathKind The kind of path being validated (root field, child field, or item of an array)
564
656
  *
565
657
  * @category types
566
- * @experimental 21.0.0
658
+ * @experimental 21.0
567
659
  */
568
660
  type TreeValidator<TValue, TPathKind extends PathKind = PathKind.Root> = LogicFn<TValue, TreeValidationResult, TPathKind>;
569
661
  /**
@@ -575,7 +667,7 @@ type TreeValidator<TValue, TPathKind extends PathKind = PathKind.Root> = LogicFn
575
667
  * @template TPathKind The kind of path being validated (root field, child field, or item of an array)
576
668
  * @see [Signal Form Validation](/guide/forms/signals/validation)
577
669
  * @category types
578
- * @experimental 21.0.0
670
+ * @experimental 21.0
579
671
  */
580
672
  type Validator<TValue, TPathKind extends PathKind = PathKind.Root> = LogicFn<TValue, ValidationResult, TPathKind>;
581
673
  /**
@@ -583,28 +675,28 @@ type Validator<TValue, TPathKind extends PathKind = PathKind.Root> = LogicFn<TVa
583
675
  * up state of other fields based on a `FieldPath`.
584
676
  *
585
677
  * @category types
586
- * @experimental 21.0.0
678
+ * @experimental 21.0
587
679
  */
588
680
  type FieldContext<TValue, TPathKind extends PathKind = PathKind.Root> = TPathKind extends PathKind.Item ? ItemFieldContext<TValue> : TPathKind extends PathKind.Child ? ChildFieldContext<TValue> : RootFieldContext<TValue>;
589
681
  /**
590
682
  * The base field context that is available for all fields.
591
683
  *
592
- * @experimental 21.0.0
684
+ * @experimental 21.0
593
685
  */
594
686
  interface RootFieldContext<TValue> {
595
687
  /** A signal containing the value of the current field. */
596
688
  readonly value: Signal<TValue>;
597
689
  /** The state of the current field. */
598
- readonly state: FieldState<TValue>;
690
+ readonly state: ReadonlyFieldState<TValue>;
599
691
  /** The current field. */
600
- readonly fieldTree: FieldTree<TValue>;
692
+ readonly fieldTree: ReadonlyFieldTree<TValue>;
601
693
  /** Gets the value of the field represented by the given path. */
602
694
  valueOf<PValue>(p: SchemaPath<PValue, SchemaPathRules>): PValue;
603
695
  /** Gets the state of the field represented by the given path. */
604
- stateOf<PControl extends AbstractControl>(p: CompatSchemaPath<PControl>): CompatFieldState<PControl>;
605
- stateOf<PValue>(p: SchemaPath<PValue, SchemaPathRules>): FieldState<PValue>;
696
+ stateOf<PControl extends AbstractControl>(p: CompatSchemaPath<PControl>): ReadonlyCompatFieldState<PControl>;
697
+ stateOf<PValue>(p: SchemaPath<PValue, SchemaPathRules>): ReadonlyFieldState<PValue>;
606
698
  /** Gets the field represented by the given path. */
607
- fieldTreeOf<PModel>(p: SchemaPathTree<PModel>): FieldTree<PModel>;
699
+ fieldTreeOf<PModel>(p: SchemaPathTree<PModel>): ReadonlyFieldTree<PModel>;
608
700
  /** The list of keys that lead from the root field to the current field. */
609
701
  readonly pathKeys: Signal<readonly string[]>;
610
702
  }
@@ -612,7 +704,7 @@ interface RootFieldContext<TValue> {
612
704
  * Field context that is available for all fields that are a child of another field.
613
705
  *
614
706
  * @category structure
615
- * @experimental 21.0.0
707
+ * @experimental 21.0
616
708
  */
617
709
  interface ChildFieldContext<TValue> extends RootFieldContext<TValue> {
618
710
  /** The key of the current field in its parent field. */
@@ -621,7 +713,7 @@ interface ChildFieldContext<TValue> extends RootFieldContext<TValue> {
621
713
  /**
622
714
  * Field context that is available for all fields that are an item in an array field.
623
715
  *
624
- * @experimental 21.0.0
716
+ * @experimental 21.0
625
717
  */
626
718
  interface ItemFieldContext<TValue> extends ChildFieldContext<TValue> {
627
719
  /** The index of the current field in its parent field. */
@@ -630,7 +722,7 @@ interface ItemFieldContext<TValue> extends ChildFieldContext<TValue> {
630
722
  /**
631
723
  * Gets the item type of an object that is possibly an array.
632
724
  *
633
- * @experimental 21.0.0
725
+ * @experimental 21.0
634
726
  */
635
727
  type ItemType<T extends Object> = T extends ReadonlyArray<any> ? T[number] : T[keyof T];
636
728
  /**
@@ -642,7 +734,7 @@ type ItemType<T extends Object> = T extends ReadonlyArray<any> ? T[number] : T[k
642
734
  * @template TValue The type of value stored in the field.
643
735
  * @template TPathKind The kind of path the debouncer is applied to (root field, child field, or item of an array).
644
736
  *
645
- * @experimental 21.0.0
737
+ * @experimental 21.0
646
738
  */
647
739
  type Debouncer<TValue, TPathKind extends PathKind = PathKind.Root> = (context: FieldContext<TValue, TPathKind>, abortSignal: AbortSignal) => Promise<void> | void;
648
740
 
@@ -908,8 +1000,8 @@ interface CombinedControl {
908
1000
  * equivalent in signal forms.
909
1001
  */
910
1002
  declare class InteropNgControl implements CombinedControl {
911
- protected field: () => FieldState<unknown>;
912
- constructor(field: () => FieldState<unknown>);
1003
+ protected field: () => ReadonlyFieldState<unknown>;
1004
+ constructor(field: () => ReadonlyFieldState<unknown>);
913
1005
  readonly control: AbstractControl<any, any>;
914
1006
  get value(): any;
915
1007
  get valid(): boolean;
@@ -965,13 +1057,16 @@ declare const FORM_FIELD: InjectionToken<FormField<unknown>>;
965
1057
  * @experimental 21.0.0
966
1058
  */
967
1059
  declare class FormField<T> {
1060
+ /**
1061
+ * The field to bind to the underlying form control.
1062
+ */
968
1063
  readonly field: i0.InputSignal<Field<T>>;
969
1064
  /**
970
1065
  * `FieldState` for the currently bound field.
971
1066
  */
972
1067
  readonly state: Signal<FieldState<T, string | number>>;
973
1068
  /**
974
- * The node injector for the element this field binding.
1069
+ * The node injector for the DOM element hosting this field binding.
975
1070
  */
976
1071
  readonly injector: Injector;
977
1072
  /**
@@ -1041,7 +1136,7 @@ interface ValidationErrorOptions {
1041
1136
  * @experimental 21.0.0
1042
1137
  */
1043
1138
  type WithFieldTree<T> = T & {
1044
- fieldTree: FieldTree<unknown>;
1139
+ fieldTree: ReadonlyFieldTree<unknown>;
1045
1140
  };
1046
1141
  /** @deprecated Use `WithFieldTree` instead */
1047
1142
  type WithField<T> = WithFieldTree<T>;
@@ -1052,7 +1147,7 @@ type WithField<T> = WithFieldTree<T>;
1052
1147
  * @experimental 21.0.0
1053
1148
  */
1054
1149
  type WithOptionalFieldTree<T> = Omit<T, 'fieldTree'> & {
1055
- fieldTree?: FieldTree<unknown>;
1150
+ fieldTree?: ReadonlyFieldTree<unknown>;
1056
1151
  };
1057
1152
  /** @deprecated Use `WithOptionalFieldTree` instead */
1058
1153
  type WithOptionalField<T> = WithOptionalFieldTree<T>;
@@ -1216,7 +1311,7 @@ declare namespace ValidationError {
1216
1311
  */
1217
1312
  interface WithFieldTree extends ValidationError {
1218
1313
  /** The field associated with this error. */
1219
- readonly fieldTree: FieldTree<unknown>;
1314
+ readonly fieldTree: ReadonlyFieldTree<unknown>;
1220
1315
  readonly formField?: FormField<unknown>;
1221
1316
  }
1222
1317
  /** @deprecated Use `ValidationError.WithFieldTree` instead */
@@ -1235,7 +1330,7 @@ declare namespace ValidationError {
1235
1330
  */
1236
1331
  interface WithOptionalFieldTree extends ValidationError {
1237
1332
  /** The field associated with this error. */
1238
- readonly fieldTree?: FieldTree<unknown>;
1333
+ readonly fieldTree?: ReadonlyFieldTree<unknown>;
1239
1334
  }
1240
1335
  /** @deprecated Use `ValidationError.WithOptionalFieldTree` instead */
1241
1336
  type WithOptionalField = WithOptionalFieldTree;
@@ -1264,7 +1359,7 @@ declare abstract class BaseNgValidationError implements ValidationError {
1264
1359
  /** Identifies the kind of error. */
1265
1360
  readonly kind: string;
1266
1361
  /** The field associated with this error. */
1267
- readonly fieldTree: FieldTree<unknown>;
1362
+ readonly fieldTree: ReadonlyFieldTree<unknown>;
1268
1363
  /** Human readable error message. */
1269
1364
  readonly message?: string;
1270
1365
  constructor(options?: ValidationErrorOptions);
@@ -1387,7 +1482,7 @@ type NgValidationError = RequiredValidationError | MinValidationError | MaxValid
1387
1482
  interface SignalFormsConfig {
1388
1483
  /** A map of CSS class names to predicate functions that determine when to apply them. */
1389
1484
  classes?: {
1390
- [className: string]: (state: FormField<unknown>) => boolean;
1485
+ [className: string]: (formField: FormFieldBinding) => boolean;
1391
1486
  };
1392
1487
  }
1393
1488
  /**
@@ -1667,4 +1762,4 @@ declare function submit<TModel>(form: FieldTree<TModel>, action: NoInfer<FormSub
1667
1762
  declare function schema<TValue>(fn: SchemaFn<TValue>): Schema<TValue>;
1668
1763
 
1669
1764
  export { BaseNgValidationError, EmailValidationError, FORM_FIELD, FormField, MAX, MAX_LENGTH, MIN, MIN_LENGTH, MaxLengthValidationError, MaxValidationError, MetadataKey, MetadataReducer, MinLengthValidationError, MinValidationError, NativeInputParseError, NgValidationError, PATTERN, PathKind, PatternValidationError, REQUIRED, RequiredValidationError, SchemaPathRules, StandardSchemaValidationError, ValidationError, apply, applyEach, applyWhen, applyWhenValue, createManagedMetadataKey, createMetadataKey, emailError, form, maxError, maxLengthError, metadata, minError, minLengthError, patternError, provideSignalFormsConfig, requiredError, schema, standardSchemaError, submit, validateStandardSchema, ɵNgFieldDirective };
1670
- export type { AsyncValidationResult, ChildFieldContext, CompatFieldState, CompatSchemaPath, Debouncer, DisabledReason, Field, FieldContext, FieldState, FieldTree, FieldValidator, FormFieldBindingOptions, FormOptions, FormSubmitOptions, IgnoreUnknownProperties, ItemFieldContext, ItemType, LogicFn, MaybeFieldTree, MaybeSchemaPathTree, MetadataSetterType, OneOrMany, ReadonlyArrayLike, RemoveStringIndexUnknownKey, RootFieldContext, Schema, SchemaFn, SchemaOrSchemaFn, SchemaPath, SchemaPathTree, SignalFormsConfig, Subfields, TreeValidationResult, TreeValidator, ValidationErrorOptions, ValidationResult, ValidationSuccess, Validator, WithField, WithFieldTree, WithOptionalField, WithOptionalFieldTree, WithoutField, WithoutFieldTree };
1765
+ export type { AsyncValidationResult, ChildFieldContext, CompatFieldState, CompatSchemaPath, Debouncer, DisabledReason, Field, FieldContext, FieldState, FieldStateByMode, FieldTree, FieldValidator, FormFieldBinding, FormFieldBindingOptions, FormOptions, FormSubmitOptions, IgnoreUnknownProperties, ItemFieldContext, ItemType, LogicFn, MaybeFieldTree, MaybeSchemaPathTree, MetadataSetterType, OneOrMany, ReadonlyArrayLike, ReadonlyCompatFieldState, ReadonlyFieldState, ReadonlyFieldTree, RemoveStringIndexUnknownKey, RootFieldContext, Schema, SchemaFn, SchemaOrSchemaFn, SchemaPath, SchemaPathTree, SignalFormsConfig, Subfields, TreeValidationResult, TreeValidator, ValidationErrorOptions, ValidationResult, ValidationSuccess, Validator, WithField, WithFieldTree, WithOptionalField, WithOptionalFieldTree, WithoutField, WithoutFieldTree };
package/types/forms.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Angular v22.0.0-next.1
2
+ * @license Angular v22.0.0-next.2
3
3
  * (c) 2010-2026 Google LLC. https://angular.dev/
4
4
  * License: MIT
5
5
  */
@@ -1,11 +1,11 @@
1
1
  /**
2
- * @license Angular v22.0.0-next.1
2
+ * @license Angular v22.0.0-next.2
3
3
  * (c) 2010-2026 Google LLC. https://angular.dev/
4
4
  * License: MIT
5
5
  */
6
6
 
7
7
  import { WritableSignal, EventEmitter } from '@angular/core';
8
- import { FormOptions, FieldTree, SchemaOrSchemaFn, ValidationError, SignalFormsConfig, SchemaFn } from './_structure-chunk.js';
8
+ import { FormOptions, FieldTree, SchemaOrSchemaFn, ValidationError, ReadonlyFieldTree, SignalFormsConfig, SchemaFn } from './_structure-chunk.js';
9
9
  import { AbstractControl, FormControlStatus, FormControlState } from '@angular/forms';
10
10
  import '@standard-schema/spec';
11
11
 
@@ -121,7 +121,7 @@ declare function compatForm<TModel>(model: WritableSignal<TModel>, schema: Schem
121
121
  declare class CompatValidationError<T = unknown> implements ValidationError {
122
122
  readonly kind: string;
123
123
  readonly control: AbstractControl;
124
- readonly fieldTree: FieldTree<unknown>;
124
+ readonly fieldTree: ReadonlyFieldTree<unknown>;
125
125
  readonly context: T;
126
126
  readonly message?: string;
127
127
  constructor({ context, kind, control }: {
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Angular v22.0.0-next.1
2
+ * @license Angular v22.0.0-next.2
3
3
  * (c) 2010-2026 Google LLC. https://angular.dev/
4
4
  * License: MIT
5
5
  */
@@ -7,7 +7,7 @@
7
7
  import * as i0 from '@angular/core';
8
8
  import { Signal, ResourceRef, InputSignal, InputSignalWithTransform, OutputRef, ModelSignal, WritableSignal } from '@angular/core';
9
9
  import { PathKind, SchemaPath, SchemaPathRules, LogicFn, OneOrMany, ValidationError, FieldValidator, FieldContext, TreeValidationResult, TreeValidator, WithOptionalFieldTree, DisabledReason, Debouncer, FieldTree } from './_structure-chunk.js';
10
- export { AsyncValidationResult, BaseNgValidationError, ChildFieldContext, CompatFieldState, CompatSchemaPath, EmailValidationError, FORM_FIELD, Field, FieldState, FormField, FormFieldBindingOptions, FormOptions, FormSubmitOptions, IgnoreUnknownProperties, ItemFieldContext, ItemType, MAX, MAX_LENGTH, MIN, MIN_LENGTH, MaxLengthValidationError, MaxValidationError, MaybeFieldTree, MaybeSchemaPathTree, MetadataKey, MetadataReducer, MetadataSetterType, MinLengthValidationError, MinValidationError, NativeInputParseError, NgValidationError, PATTERN, PatternValidationError, REQUIRED, ReadonlyArrayLike, RemoveStringIndexUnknownKey, RequiredValidationError, RootFieldContext, Schema, SchemaFn, SchemaOrSchemaFn, SchemaPathTree, SignalFormsConfig, StandardSchemaValidationError, Subfields, ValidationErrorOptions, ValidationResult, ValidationSuccess, Validator, WithField, WithFieldTree, WithOptionalField, WithoutField, WithoutFieldTree, apply, applyEach, applyWhen, applyWhenValue, createManagedMetadataKey, createMetadataKey, emailError, form, maxError, maxLengthError, metadata, minError, minLengthError, patternError, provideSignalFormsConfig, requiredError, schema, standardSchemaError, submit, validateStandardSchema, ɵNgFieldDirective } from './_structure-chunk.js';
10
+ export { AsyncValidationResult, BaseNgValidationError, ChildFieldContext, CompatFieldState, CompatSchemaPath, EmailValidationError, FORM_FIELD, Field, FieldState, FieldStateByMode, FormField, FormFieldBinding, FormFieldBindingOptions, FormOptions, FormSubmitOptions, IgnoreUnknownProperties, ItemFieldContext, ItemType, MAX, MAX_LENGTH, MIN, MIN_LENGTH, MaxLengthValidationError, MaxValidationError, MaybeFieldTree, MaybeSchemaPathTree, MetadataKey, MetadataReducer, MetadataSetterType, MinLengthValidationError, MinValidationError, NativeInputParseError, NgValidationError, PATTERN, PatternValidationError, REQUIRED, ReadonlyArrayLike, ReadonlyCompatFieldState, ReadonlyFieldState, ReadonlyFieldTree, RemoveStringIndexUnknownKey, RequiredValidationError, RootFieldContext, Schema, SchemaFn, SchemaOrSchemaFn, SchemaPathTree, SignalFormsConfig, StandardSchemaValidationError, Subfields, ValidationErrorOptions, ValidationResult, ValidationSuccess, Validator, WithField, WithFieldTree, WithOptionalField, WithoutField, WithoutFieldTree, apply, applyEach, applyWhen, applyWhenValue, createManagedMetadataKey, createMetadataKey, emailError, form, maxError, maxLengthError, metadata, minError, minLengthError, patternError, provideSignalFormsConfig, requiredError, schema, standardSchemaError, submit, validateStandardSchema, ɵNgFieldDirective } from './_structure-chunk.js';
11
11
  import { HttpResourceRequest, HttpResourceOptions } from '@angular/common/http';
12
12
  import '@angular/forms';
13
13
  import '@standard-schema/spec';