@angular/forms 21.2.0-next.0 → 21.2.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/types/forms.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Angular v21.2.0-next.0
2
+ * @license Angular v21.2.0-next.2
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.2.0-next.0
2
+ * @license Angular v21.2.0-next.2
3
3
  * (c) 2010-2026 Google LLC. https://angular.dev/
4
4
  * License: MIT
5
5
  */
6
6
 
7
- import { WritableSignal } from '@angular/core';
8
- import { FormOptions, FieldTree, SchemaOrSchemaFn, ValidationError, SignalFormsConfig } from './_structure-chunk.js';
9
- import { AbstractControl } from '@angular/forms';
7
+ import { WritableSignal, EventEmitter } from '@angular/core';
8
+ import { FormOptions, FieldTree, SchemaOrSchemaFn, ValidationError, SignalFormsConfig, SchemaFn } from './_structure-chunk.js';
9
+ import { AbstractControl, FormControlStatus, FormControlState } from '@angular/forms';
10
10
  import '@standard-schema/spec';
11
11
 
12
12
  /**
@@ -15,7 +15,7 @@ import '@standard-schema/spec';
15
15
  * @category interop
16
16
  * @experimental 21.0.0
17
17
  */
18
- type CompatFormOptions = Omit<FormOptions, 'adapter'>;
18
+ type CompatFormOptions<TModel> = Omit<FormOptions<TModel>, 'adapter'>;
19
19
  /**
20
20
  * Creates a compatibility form wrapped around the given model data.
21
21
  *
@@ -78,7 +78,7 @@ declare function compatForm<TModel>(model: WritableSignal<TModel>): FieldTree<TM
78
78
  * @category interop
79
79
  * @experimental 21.0.0
80
80
  */
81
- declare function compatForm<TModel>(model: WritableSignal<TModel>, schemaOrOptions: SchemaOrSchemaFn<TModel> | CompatFormOptions): FieldTree<TModel>;
81
+ declare function compatForm<TModel>(model: WritableSignal<TModel>, schemaOrOptions: SchemaOrSchemaFn<TModel> | CompatFormOptions<TModel>): FieldTree<TModel>;
82
82
  /**
83
83
  * Creates a compatibility form wrapped around the given model data.
84
84
  *
@@ -110,7 +110,7 @@ declare function compatForm<TModel>(model: WritableSignal<TModel>, schemaOrOptio
110
110
  * @category interop
111
111
  * @experimental 21.0.0
112
112
  */
113
- declare function compatForm<TModel>(model: WritableSignal<TModel>, schema: SchemaOrSchemaFn<TModel>, options: CompatFormOptions): FieldTree<TModel>;
113
+ declare function compatForm<TModel>(model: WritableSignal<TModel>, schema: SchemaOrSchemaFn<TModel>, options: CompatFormOptions<TModel>): FieldTree<TModel>;
114
114
 
115
115
  /**
116
116
  * An error used for compat errors.
@@ -139,5 +139,128 @@ declare class CompatValidationError<T = unknown> implements ValidationError {
139
139
  */
140
140
  declare const NG_STATUS_CLASSES: SignalFormsConfig['classes'];
141
141
 
142
- export { CompatValidationError, NG_STATUS_CLASSES, compatForm };
142
+ /** Options used to update the control value. */
143
+ type ValueUpdateOptions = {
144
+ onlySelf?: boolean;
145
+ emitEvent?: boolean;
146
+ emitModelToViewChange?: boolean;
147
+ emitViewToModelChange?: boolean;
148
+ };
149
+ /**
150
+ * A `FormControl` that is backed by signal forms rules.
151
+ *
152
+ * This class provides a bridge between Signal Forms and Reactive Forms, allowing
153
+ * signal-based controls to be used within a standard `FormGroup` or `FormArray`.
154
+ *
155
+ * A control could be created using signal forms, and integrated with an existing FormGroup
156
+ * propagating all the statuses and validity.
157
+ *
158
+ * @usageNotes
159
+ *
160
+ * ### Basic usage
161
+ *
162
+ * ```angular-ts
163
+ * const form = new FormGroup({
164
+ * // You can create SignalFormControl with signal form rules, and add it to a FormGroup.
165
+ * name: new SignalFormControl('Alice', p => {
166
+ * required(p);
167
+ * }),
168
+ * age: new FormControl(25),
169
+ * });
170
+ * ```
171
+ * In the template you can get the underlying `fieldTree` and bind it:
172
+ *
173
+ * ```angular-html
174
+ * <form [formGroup]="form">
175
+ * <input [formField]="nameControl.fieldTree" />
176
+ * <input formControlName="age" />
177
+ * </form>
178
+ * ```
179
+ *
180
+ * @experimental
181
+ */
182
+ declare class SignalFormControl<T> extends AbstractControl {
183
+ /** Source FieldTree. */
184
+ readonly fieldTree: FieldTree<T>;
185
+ /** The raw signal driving the control value. */
186
+ readonly sourceValue: WritableSignal<T>;
187
+ private readonly fieldState;
188
+ private readonly initialValue;
189
+ private pendingParentNotifications;
190
+ private readonly onChangeCallbacks;
191
+ private readonly onDisabledChangeCallbacks;
192
+ readonly valueChanges: EventEmitter<T>;
193
+ readonly statusChanges: EventEmitter<FormControlStatus>;
194
+ constructor(value: T, schemaOrOptions?: SchemaFn<T> | FormOptions<T>, options?: FormOptions<T>);
195
+ /**
196
+ * Defines properties using closure-safe names to prevent issues with property renaming optimizations.
197
+ *
198
+ * AbstractControl have `value` and `errors` as readonly prop, which doesn't allow getters.
199
+ **/
200
+ private defineCompatProperties;
201
+ private emitControlEvent;
202
+ setValue(value: any, options?: ValueUpdateOptions): void;
203
+ patchValue(value: any, options?: ValueUpdateOptions): void;
204
+ private updateValue;
205
+ registerOnChange(fn: (value?: any, emitModelEvent?: boolean) => void): void;
206
+ registerOnDisabledChange(fn: (isDisabled: boolean) => void): void;
207
+ getRawValue(): T;
208
+ reset(value?: T | FormControlState<T>, options?: ValueUpdateOptions): void;
209
+ private scheduleParentUpdate;
210
+ private notifyParentUnlessPending;
211
+ private updateParentValueAndValidity;
212
+ private propagateToParent;
213
+ get status(): FormControlStatus;
214
+ get valid(): boolean;
215
+ get invalid(): boolean;
216
+ get pending(): boolean;
217
+ get disabled(): boolean;
218
+ get enabled(): boolean;
219
+ get dirty(): boolean;
220
+ set dirty(_: boolean);
221
+ get pristine(): boolean;
222
+ set pristine(_: boolean);
223
+ get touched(): boolean;
224
+ set touched(_: boolean);
225
+ get untouched(): boolean;
226
+ set untouched(_: boolean);
227
+ markAsTouched(opts?: {
228
+ onlySelf?: boolean;
229
+ }): void;
230
+ markAsDirty(opts?: {
231
+ onlySelf?: boolean;
232
+ }): void;
233
+ markAsPristine(opts?: {
234
+ onlySelf?: boolean;
235
+ }): void;
236
+ markAsUntouched(opts?: {
237
+ onlySelf?: boolean;
238
+ }): void;
239
+ updateValueAndValidity(_opts?: Object): void;
240
+ disable(_opts?: {
241
+ onlySelf?: boolean;
242
+ emitEvent?: boolean;
243
+ }): void;
244
+ enable(_opts?: {
245
+ onlySelf?: boolean;
246
+ emitEvent?: boolean;
247
+ }): void;
248
+ setValidators(_validators: any): void;
249
+ setAsyncValidators(_validators: any): void;
250
+ addValidators(_validators: any): void;
251
+ addAsyncValidators(_validators: any): void;
252
+ removeValidators(_validators: any): void;
253
+ removeAsyncValidators(_validators: any): void;
254
+ clearValidators(): void;
255
+ clearAsyncValidators(): void;
256
+ setErrors(_errors: any, _opts?: {
257
+ emitEvent?: boolean;
258
+ }): void;
259
+ markAsPending(_opts?: {
260
+ onlySelf?: boolean;
261
+ emitEvent?: boolean;
262
+ }): void;
263
+ }
264
+
265
+ export { CompatValidationError, NG_STATUS_CLASSES, SignalFormControl, compatForm };
143
266
  export type { CompatFormOptions };
@@ -1,15 +1,15 @@
1
1
  /**
2
- * @license Angular v21.2.0-next.0
2
+ * @license Angular v21.2.0-next.2
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
- 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, 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
- import { StandardSchemaV1 } from '@standard-schema/spec';
8
+ import { PathKind, SchemaPath, SchemaPathRules, LogicFn, OneOrMany, ValidationError, FieldValidator, FieldContext, TreeValidationResult, TreeValidator, WithOptionalFieldTree, DisabledReason, Debouncer } from './_structure-chunk.js';
9
+ export { AsyncValidationResult, BaseNgValidationError, ChildFieldContext, CompatFieldState, CompatSchemaPath, EmailValidationError, FORM_FIELD, FieldState, FieldTree, FormField, FormFieldBindingOptions, FormOptions, FormSubmitOptions, IgnoreUnknownProperties, ItemFieldContext, ItemType, MAX, MAX_LENGTH, MIN, MIN_LENGTH, MaxLengthValidationError, MaxValidationError, MaybeFieldTree, MaybeSchemaPathTree, MetadataKey, MetadataReducer, MetadataSetterType, MinLengthValidationError, MinValidationError, 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';
11
10
  import { HttpResourceRequest, HttpResourceOptions } from '@angular/common/http';
12
11
  import '@angular/forms';
12
+ import '@standard-schema/spec';
13
13
 
14
14
  /**
15
15
  * Adds logic to a field to conditionally disable it. A disabled field does not contribute to the
@@ -216,41 +216,6 @@ declare function required<TValue, TPathKind extends PathKind = PathKind.Root>(pa
216
216
  when?: NoInfer<LogicFn<TValue, boolean, TPathKind>>;
217
217
  }): void;
218
218
 
219
- /**
220
- * Utility type that removes a string index key when its value is `unknown`,
221
- * i.e. `{[key: string]: unknown}`. It allows specific string keys to pass through, even if their
222
- * value is `unknown`, e.g. `{key: unknown}`.
223
- *
224
- * @experimental 21.0.0
225
- */
226
- type RemoveStringIndexUnknownKey<K, V> = string extends K ? unknown extends V ? never : K : K;
227
- /**
228
- * Utility type that recursively ignores unknown string index properties on the given object.
229
- * We use this on the `TSchema` type in `validateStandardSchema` in order to accommodate Zod's
230
- * `looseObject` which includes `{[key: string]: unknown}` as part of the type.
231
- *
232
- * @experimental 21.0.0
233
- */
234
- type IgnoreUnknownProperties<T> = T extends Record<PropertyKey, unknown> ? {
235
- [K in keyof T as RemoveStringIndexUnknownKey<K, T[K]>]: IgnoreUnknownProperties<T[K]>;
236
- } : T;
237
- /**
238
- * Validates a field using a `StandardSchemaV1` compatible validator (e.g. a Zod validator).
239
- *
240
- * See https://github.com/standard-schema/standard-schema for more about standard schema.
241
- *
242
- * @param path The `FieldPath` to the field to validate.
243
- * @param schema The standard schema compatible validator to use for validation.
244
- * @template TSchema The type validated by the schema. This may be either the full `TValue` type,
245
- * or a partial of it.
246
- * @template TValue The type of value stored in the field being validated.
247
- *
248
- * @see [Signal Form Schema Validation](guide/forms/signals/validation#integration-with-schema-validation-libraries)
249
- * @category validation
250
- * @experimental 21.0.0
251
- */
252
- declare function validateStandardSchema<TSchema, TModel extends IgnoreUnknownProperties<TSchema>>(path: SchemaPath<TModel> & SchemaPathTree<TModel>, schema: StandardSchemaV1<TSchema>): void;
253
-
254
219
  /**
255
220
  * Adds logic to a field to determine if the field has validation errors.
256
221
  *
@@ -423,12 +388,12 @@ declare function validateTree<TValue, TPathKind extends PathKind = PathKind.Root
423
388
  * @category control
424
389
  * @experimental 21.0.0
425
390
  */
426
- interface FormUiControl {
391
+ interface FormUiControl<TValue> {
427
392
  /**
428
393
  * An input to receive the errors for the field. If implemented, the `Field` directive will
429
394
  * automatically bind errors from the bound field to this input.
430
395
  */
431
- readonly errors?: InputSignal<readonly WithOptionalField<ValidationError>[]> | InputSignalWithTransform<readonly WithOptionalField<ValidationError>[], unknown>;
396
+ readonly errors?: InputSignal<readonly ValidationError.WithOptionalFieldTree[]> | InputSignalWithTransform<readonly ValidationError.WithOptionalFieldTree[], unknown>;
432
397
  /**
433
398
  * An input to receive the disabled status for the field. If implemented, the `Field` directive
434
399
  * will automatically bind the disabled status from the bound field to this input.
@@ -438,7 +403,7 @@ interface FormUiControl {
438
403
  * An input to receive the reasons for the disablement of the field. If implemented, the `Field`
439
404
  * directive will automatically bind the disabled reason from the bound field to this input.
440
405
  */
441
- readonly disabledReasons?: InputSignal<readonly WithOptionalField<DisabledReason>[]> | InputSignalWithTransform<readonly WithOptionalField<DisabledReason>[], unknown>;
406
+ readonly disabledReasons?: InputSignal<readonly WithOptionalFieldTree<DisabledReason>[]> | InputSignalWithTransform<readonly WithOptionalFieldTree<DisabledReason>[], unknown>;
442
407
  /**
443
408
  * An input to receive the readonly status for the field. If implemented, the `Field` directive
444
409
  * will automatically bind the readonly status from the bound field to this input.
@@ -504,6 +469,12 @@ interface FormUiControl {
504
469
  * will automatically bind the value patterns from the bound field to this input.
505
470
  */
506
471
  readonly pattern?: InputSignal<readonly RegExp[]> | InputSignalWithTransform<readonly RegExp[], unknown>;
472
+ /**
473
+ * A signal containing the current parse errors for the control.
474
+ * This allows the control to communicate to the form that there are additional validation errors
475
+ * beyond those produced by the schema, due to being unable to parse the user's input.
476
+ */
477
+ readonly parseErrors?: Signal<ValidationError.WithoutFieldTree[]>;
507
478
  /**
508
479
  * Focuses the UI control.
509
480
  *
@@ -525,7 +496,7 @@ interface FormUiControl {
525
496
  * @category control
526
497
  * @experimental 21.0.0
527
498
  */
528
- interface FormValueControl<TValue> extends FormUiControl {
499
+ interface FormValueControl<TValue> extends FormUiControl<TValue> {
529
500
  /**
530
501
  * The value is the only required property in this contract. A component that wants to integrate
531
502
  * with the `Field` directive via this contract, *must* provide a `model()` that will be kept in
@@ -549,7 +520,7 @@ interface FormValueControl<TValue> extends FormUiControl {
549
520
  * @category control
550
521
  * @experimental 21.0.0
551
522
  */
552
- interface FormCheckboxControl extends FormUiControl {
523
+ interface FormCheckboxControl extends FormUiControl<boolean> {
553
524
  /**
554
525
  * The checked is the only required property in this contract. A component that wants to integrate
555
526
  * with the `Field` directive, *must* provide a `model()` that will be kept in sync with the
@@ -577,5 +548,5 @@ interface FormCheckboxControl extends FormUiControl {
577
548
  */
578
549
  declare function debounce<TValue, TPathKind extends PathKind = PathKind.Root>(path: SchemaPath<TValue, SchemaPathRules.Supported, TPathKind>, durationOrDebouncer: number | Debouncer<TValue, TPathKind>): void;
579
550
 
580
- export { Debouncer, DisabledReason, FieldContext, FieldValidator, LogicFn, OneOrMany, PathKind, SchemaPath, SchemaPathRules, SchemaPathTree, TreeValidationResult, TreeValidator, ValidationError, WithOptionalField, debounce, disabled, email, hidden, max, maxLength, min, minLength, pattern, readonly, required, validate, validateAsync, validateHttp, validateStandardSchema, validateTree };
581
- export type { AsyncValidatorOptions, FormCheckboxControl, FormUiControl, FormValueControl, HttpValidatorOptions, IgnoreUnknownProperties, MapToErrorsFn, RemoveStringIndexUnknownKey };
551
+ export { Debouncer, DisabledReason, FieldContext, FieldValidator, LogicFn, OneOrMany, PathKind, SchemaPath, SchemaPathRules, TreeValidationResult, TreeValidator, ValidationError, WithOptionalFieldTree, debounce, disabled, email, hidden, max, maxLength, min, minLength, pattern, readonly, required, validate, validateAsync, validateHttp, validateTree };
552
+ export type { AsyncValidatorOptions, FormCheckboxControl, FormUiControl, FormValueControl, HttpValidatorOptions, MapToErrorsFn };