@angular/forms 21.1.0-rc.0 → 21.1.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.1.0-rc.0
2
+ * @license Angular v21.1.1
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 { InjectionToken, Injector, ɵCONTROL as _CONTROL, ɵɵcontrolCreate as __controlCreate, ɵcontrolUpdate as _controlUpdate, Signal, ɵFieldState as _FieldState, Provider, WritableSignal, DestroyableInjector } from '@angular/core';
8
+ import { ɵFormFieldBindingOptions as _FormFieldBindingOptions, InjectionToken, Injector, ɵCONTROL as _CONTROL, ɵɵcontrolCreate as __controlCreate, ɵcontrolUpdate as _controlUpdate, Signal, ɵFieldState as _FieldState, Provider, WritableSignal, DestroyableInjector } 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';
@@ -42,52 +42,15 @@ declare class InteropNgControl implements Pick<NgControl, InteropSharedKeys | 'c
42
42
  updateValueAndValidity(): void;
43
43
  }
44
44
 
45
- /**
46
- * Lightweight DI token provided by the {@link Field} directive.
47
- *
48
- * @category control
49
- * @experimental 21.0.0
50
- */
51
- declare const FIELD: InjectionToken<Field<unknown>>;
52
- /**
53
- * Binds a form `FieldTree` to a UI control that edits it. A UI control can be one of several things:
54
- * 1. A native HTML input or textarea
55
- * 2. A signal forms custom control that implements `FormValueControl` or `FormCheckboxControl`
56
- * 3. A component that provides a `ControlValueAccessor`. This should only be used for backwards
57
- * compatibility with reactive forms. Prefer options (1) and (2).
58
- *
59
- * This directive has several responsibilities:
60
- * 1. Two-way binds the field's value with the UI control's value
61
- * 2. Binds additional forms related state on the field to the UI control (disabled, required, etc.)
62
- * 3. Relays relevant events on the control to the field (e.g. marks field touched on blur)
63
- * 4. Provides a fake `NgControl` that implements a subset of the features available on the
64
- * reactive forms `NgControl`. This is provided to improve interoperability with controls
65
- * designed to work with reactive forms. It should not be used by controls written for signal
66
- * forms.
67
- *
68
- * @category control
69
- * @experimental 21.0.0
70
- */
71
- declare class Field<T> {
72
- readonly element: HTMLElement;
73
- readonly injector: Injector;
74
- readonly field: i0.InputSignal<FieldTree<T>>;
75
- readonly state: i0.Signal<[T] extends [_angular_forms.AbstractControl<any, any, any>] ? CompatFieldState<T, string | number> : FieldState<T, string | number>>;
76
- readonly [_CONTROL]: {
77
- readonly create: typeof __controlCreate;
78
- readonly update: typeof _controlUpdate;
79
- };
80
- private config;
81
- /** Any `ControlValueAccessor` instances provided on the host element. */
82
- private readonly controlValueAccessors;
83
- /** A lazily instantiated fake `NgControl`. */
84
- private interopNgControl;
85
- /** Lazily instantiates a fake `NgControl` for this field. */
86
- protected getOrCreateNgControl(): InteropNgControl;
87
- static ɵfac: i0.ɵɵFactoryDeclaration<Field<any>, never>;
88
- static ɵdir: i0.ɵɵDirectiveDeclaration<Field<any>, "[field]", never, { "field": { "alias": "field"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
45
+ interface FormFieldBindingOptions extends _FormFieldBindingOptions {
46
+ /**
47
+ * Focuses the binding.
48
+ *
49
+ * If not specified, Signal Forms will attempt to focus the host element of the `FormField` when
50
+ * asked to focus this binding.
51
+ */
52
+ focus?: VoidFunction;
89
53
  }
90
-
91
54
  /**
92
55
  * Lightweight DI token provided by the {@link FormField} directive.
93
56
  *
@@ -119,6 +82,7 @@ declare class FormField<T> {
119
82
  readonly injector: Injector;
120
83
  readonly formField: i0.InputSignal<FieldTree<T>>;
121
84
  readonly state: i0.Signal<[T] extends [_angular_forms.AbstractControl<any, any, any>] ? CompatFieldState<T, string | number> : FieldState<T, string | number>>;
85
+ private readonly bindingOptions;
122
86
  readonly [_CONTROL]: {
123
87
  readonly create: typeof __controlCreate;
124
88
  readonly update: typeof _controlUpdate;
@@ -130,6 +94,15 @@ declare class FormField<T> {
130
94
  private interopNgControl;
131
95
  /** Lazily instantiates a fake `NgControl` for this form field. */
132
96
  protected getOrCreateNgControl(): InteropNgControl;
97
+ /**
98
+ * Registers this `FormField` as a binding on its associated `FieldState`.
99
+ *
100
+ * This method should be called at most once for a given `FormField`. A `FormField` placed on a
101
+ * custom control (`FormUiControl`) automatically registers that custom control as a binding.
102
+ */
103
+ registerAsBinding(bindingOptions?: FormFieldBindingOptions): void;
104
+ /** Focuses this UI control. */
105
+ focus(): void;
133
106
  static ɵfac: i0.ɵɵFactoryDeclaration<FormField<any>, never>;
134
107
  static ɵdir: i0.ɵɵDirectiveDeclaration<FormField<any>, "[formField]", never, { "formField": { "alias": "formField"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
135
108
  }
@@ -342,13 +315,6 @@ declare namespace PathKind {
342
315
  [ɵɵTYPE]: 'item';
343
316
  }
344
317
  }
345
- /**
346
- * A status indicating whether a field is unsubmitted, submitted, or currently submitting.
347
- *
348
- * @category types
349
- * @experimental 21.0.0
350
- */
351
- type SubmittedStatus = 'unsubmitted' | 'submitted' | 'submitting';
352
318
  /**
353
319
  * A reason for a field's disablement.
354
320
  *
@@ -526,9 +492,9 @@ interface FieldState<TValue, TKey extends string | number = string | number> ext
526
492
  */
527
493
  readonly keyInParent: Signal<TKey>;
528
494
  /**
529
- * The {@link Field} directives that bind this field to a UI control.
495
+ * The {@link FormField} directives that bind this field to a UI control.
530
496
  */
531
- readonly formFieldBindings: Signal<readonly (Field<unknown> | FormField<unknown>)[]>;
497
+ readonly formFieldBindings: Signal<readonly FormField<unknown>[]>;
532
498
  /**
533
499
  * Reads a metadata value from the field.
534
500
  * @param key The metadata key to read.
@@ -542,6 +508,11 @@ interface FieldState<TValue, TKey extends string | number = string | number> ext
542
508
  * @param value Optional value to set to the form. If not passed, the value will not be changed.
543
509
  */
544
510
  reset(value?: TValue): void;
511
+ /**
512
+ * Focuses the first UI control in the DOM that is bound to this field state.
513
+ * If no UI control is bound, does nothing.
514
+ */
515
+ focusBoundControl(): void;
545
516
  }
546
517
  /**
547
518
  * This is FieldState also providing access to the wrapped FormControl.
@@ -1171,7 +1142,7 @@ type NgValidationError = RequiredValidationError | MinValidationError | MaxValid
1171
1142
  interface SignalFormsConfig {
1172
1143
  /** A map of CSS class names to predicate functions that determine when to apply them. */
1173
1144
  classes?: {
1174
- [className: string]: (state: Field<unknown> | FormField<unknown>) => boolean;
1145
+ [className: string]: (state: FormField<unknown>) => boolean;
1175
1146
  };
1176
1147
  }
1177
1148
  /**
@@ -1572,7 +1543,7 @@ declare class FieldNodeState {
1572
1543
  */
1573
1544
  markAsUntouched(): void;
1574
1545
  /** The {@link FormField} directives that bind this field to a UI control. */
1575
- readonly formFieldBindings: i0.WritableSignal<readonly (Field<unknown> | FormField<unknown>)[]>;
1546
+ readonly formFieldBindings: i0.WritableSignal<readonly FormField<unknown>[]>;
1576
1547
  constructor(node: FieldNode);
1577
1548
  /**
1578
1549
  * Whether this field is considered dirty.
@@ -1773,6 +1744,16 @@ declare class FieldNode implements FieldState<unknown> {
1773
1744
  readonly fieldProxy: FieldTree<any>;
1774
1745
  private readonly pathNode;
1775
1746
  constructor(options: FieldNodeOptions);
1747
+ focusBoundControl(): void;
1748
+ /**
1749
+ * Gets the Field directive binding that should be focused when the developer calls
1750
+ * `focusBoundControl` on this node.
1751
+ *
1752
+ * This will prioritize focusable bindings to this node, and if multiple exist, it will return
1753
+ * the first one in the DOM. If no focusable bindings exist on this node, it will return the
1754
+ * first focusable binding in the DOM for any descendant node of this one.
1755
+ */
1756
+ private getBindingForFocus;
1776
1757
  /**
1777
1758
  * The `AbortController` for the currently debounced sync, or `undefined` if there is none.
1778
1759
  *
@@ -1797,7 +1778,7 @@ declare class FieldNode implements FieldState<unknown> {
1797
1778
  get disabledReasons(): Signal<readonly DisabledReason[]>;
1798
1779
  get hidden(): Signal<boolean>;
1799
1780
  get readonly(): Signal<boolean>;
1800
- get formFieldBindings(): Signal<readonly (Field<unknown> | FormField<unknown>)[]>;
1781
+ get formFieldBindings(): Signal<readonly FormField<unknown>[]>;
1801
1782
  get submitting(): Signal<boolean>;
1802
1783
  get name(): Signal<string>;
1803
1784
  get max(): Signal<number | undefined> | undefined;
@@ -1834,6 +1815,10 @@ declare class FieldNode implements FieldState<unknown> {
1834
1815
  * Synchronizes the {@link controlValue} with the {@link value} signal immediately.
1835
1816
  */
1836
1817
  private sync;
1818
+ /**
1819
+ * If there is a pending sync, abort it and sync immediately.
1820
+ */
1821
+ private flushSync;
1837
1822
  /**
1838
1823
  * Initiates a debounced {@link sync}.
1839
1824
  *
@@ -1906,7 +1891,7 @@ declare abstract class FieldNodeStructure {
1906
1891
  get injector(): DestroyableInjector;
1907
1892
  constructor(logic: LogicNode, node: FieldNode, createChildNode: ChildNodeCtor);
1908
1893
  /** Gets the child fields of this field. */
1909
- children(): Iterable<FieldNode>;
1894
+ children(): readonly FieldNode[];
1910
1895
  /** Retrieve a child `FieldNode` of this node by property key. */
1911
1896
  getChild(key: PropertyKey): FieldNode | undefined;
1912
1897
  /**
@@ -2357,7 +2342,7 @@ declare function applyWhenValue<TValue>(path: SchemaPath<TValue>, predicate: (va
2357
2342
  /**
2358
2343
  * Submits a given `FieldTree` using the given action function and applies any submission errors
2359
2344
  * resulting from the action to the field. Submission errors returned by the `action` will be integrated
2360
- * into the field as a `ValidationError` on the sub-field indicated by the `field` property of the
2345
+ * into the field as a `ValidationError` on the sub-field indicated by the `fieldTree` property of the
2361
2346
  * submission error.
2362
2347
  *
2363
2348
  * @example
@@ -2366,8 +2351,9 @@ declare function applyWhenValue<TValue>(path: SchemaPath<TValue>, predicate: (va
2366
2351
  * const result = await myClient.registerNewUser(registrationForm().value());
2367
2352
  * if (result.errorCode === myClient.ErrorCode.USERNAME_TAKEN) {
2368
2353
  * return [{
2369
- * field: registrationForm.username,
2370
- * error: {kind: 'server', message: 'Username already taken'}
2354
+ * fieldTree: registrationForm.username,
2355
+ * kind: 'server',
2356
+ * message: 'Username already taken'
2371
2357
  * }];
2372
2358
  * }
2373
2359
  * return undefined;
@@ -2400,5 +2386,5 @@ declare function submit<TModel>(form: FieldTree<TModel>, action: (form: FieldTre
2400
2386
  */
2401
2387
  declare function schema<TValue>(fn: SchemaFn<TValue>): Schema<TValue>;
2402
2388
 
2403
- export { EmailValidationError, FIELD, FORM_FIELD, Field, FormField, 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, emailError, form, maxError, maxLengthError, metadata, minError, minLengthError, patternError, provideSignalFormsConfig, requiredError, schema, standardSchemaError, submit };
2404
- 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 };
2389
+ export { EmailValidationError, FORM_FIELD, FormField, 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, emailError, form, maxError, maxLengthError, metadata, minError, minLengthError, patternError, provideSignalFormsConfig, requiredError, schema, standardSchemaError, submit };
2390
+ export type { AsyncValidationResult, ChildFieldContext, CompatFieldState, CompatSchemaPath, Debouncer, DisabledReason, FieldContext, FieldState, FieldTree, FieldValidator, FormFieldBindingOptions, FormOptions, ItemFieldContext, ItemType, LogicFn, MaybeFieldTree, MaybeSchemaPathTree, MetadataSetterType, OneOrMany, ReadonlyArrayLike, RootFieldContext, Schema, SchemaFn, SchemaOrSchemaFn, SchemaPath, SchemaPathTree, SignalFormsConfig, Subfields, TreeValidationResult, TreeValidator, ValidationResult, ValidationSuccess, Validator, WithField, WithOptionalField, WithoutField };
package/types/forms.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Angular v21.1.0-rc.0
2
+ * @license Angular v21.1.1
3
3
  * (c) 2010-2026 Google LLC. https://angular.dev/
4
4
  * License: MIT
5
5
  */
@@ -4538,7 +4538,7 @@ declare class NgForm extends ControlContainer implements Form, AfterViewInit {
4538
4538
  * and `FormArray` instances to child `FormControlName`, `FormGroupName`,
4539
4539
  * and `FormArrayName` directives.
4540
4540
  *
4541
- * @see [Reactive Forms Guide](guide/reactive-forms)
4541
+ * @see [Reactive Forms Guide](guide/forms/reactive-forms)
4542
4542
  * @see {@link AbstractControl}
4543
4543
  *
4544
4544
  * @usageNotes
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Angular v21.1.0-rc.0
2
+ * @license Angular v21.1.1
3
3
  * (c) 2010-2026 Google LLC. https://angular.dev/
4
4
  * License: MIT
5
5
  */
@@ -1,12 +1,12 @@
1
1
  /**
2
- * @license Angular v21.1.0-rc.0
2
+ * @license Angular v21.1.1
3
3
  * (c) 2010-2026 Google LLC. https://angular.dev/
4
4
  * License: MIT
5
5
  */
6
6
 
7
7
  import { Signal, ResourceRef, InputSignal, InputSignalWithTransform, ModelSignal, OutputRef } from '@angular/core';
8
8
  import { PathKind, SchemaPath, SchemaPathRules, LogicFn, OneOrMany, ValidationError, SchemaPathTree, FieldValidator, FieldContext, TreeValidationResult, TreeValidator, WithOptionalField, DisabledReason, Debouncer } from './_structure-chunk.js';
9
- export { AsyncValidationResult, ChildFieldContext, CompatFieldState, CompatSchemaPath, EmailValidationError, FIELD, FORM_FIELD, Field, FieldState, FieldTree, FormField, FormOptions, ItemFieldContext, ItemType, MAX, MAX_LENGTH, MIN, MIN_LENGTH, MaxLengthValidationError, MaxValidationError, MaybeFieldTree, MaybeSchemaPathTree, MetadataKey, MetadataReducer, MetadataSetterType, MinLengthValidationError, MinValidationError, NgValidationError, PATTERN, PatternValidationError, REQUIRED, ReadonlyArrayLike, RequiredValidationError, RootFieldContext, Schema, SchemaFn, SchemaOrSchemaFn, SignalFormsConfig, StandardSchemaValidationError, Subfields, SubmittedStatus, ValidationResult, ValidationSuccess, Validator, WithField, WithoutField, apply, applyEach, applyWhen, applyWhenValue, createManagedMetadataKey, createMetadataKey, emailError, form, maxError, maxLengthError, metadata, minError, minLengthError, patternError, provideSignalFormsConfig, requiredError, schema, standardSchemaError, submit } from './_structure-chunk.js';
9
+ export { AsyncValidationResult, ChildFieldContext, CompatFieldState, CompatSchemaPath, EmailValidationError, FORM_FIELD, FieldState, FieldTree, FormField, FormFieldBindingOptions, FormOptions, ItemFieldContext, ItemType, MAX, MAX_LENGTH, MIN, MIN_LENGTH, MaxLengthValidationError, MaxValidationError, MaybeFieldTree, MaybeSchemaPathTree, MetadataKey, MetadataReducer, MetadataSetterType, MinLengthValidationError, MinValidationError, NgValidationError, PATTERN, PatternValidationError, REQUIRED, ReadonlyArrayLike, RequiredValidationError, RootFieldContext, Schema, SchemaFn, SchemaOrSchemaFn, SignalFormsConfig, StandardSchemaValidationError, Subfields, ValidationResult, ValidationSuccess, Validator, WithField, WithoutField, apply, applyEach, applyWhen, applyWhenValue, createManagedMetadataKey, createMetadataKey, emailError, form, maxError, maxLengthError, metadata, minError, minLengthError, patternError, provideSignalFormsConfig, requiredError, schema, standardSchemaError, submit } from './_structure-chunk.js';
10
10
  import { StandardSchemaV1 } from '@standard-schema/spec';
11
11
  import { HttpResourceRequest, HttpResourceOptions } from '@angular/common/http';
12
12
  import '@angular/forms';
@@ -504,6 +504,13 @@ interface FormUiControl {
504
504
  * will automatically bind the value patterns from the bound field to this input.
505
505
  */
506
506
  readonly pattern?: InputSignal<readonly RegExp[]> | InputSignalWithTransform<readonly RegExp[], unknown>;
507
+ /**
508
+ * Focuses the UI control.
509
+ *
510
+ * If the focus method is not implemented, Signal Forms will attempt to focus the host element
511
+ * when asked to focus this control.
512
+ */
513
+ focus?(): void;
507
514
  }
508
515
  /**
509
516
  * A contract for a form control that edits a `FieldTree` of type `TValue`. Any component that