angular/angular
@angular/forms
Form-handling APIs: reactive forms (FormControl, FormGroup, FormArray), template-driven forms (NgModel, NgForm), validators, and the new signal forms package shipped at @angular/forms/signals.
Purpose
The package supports two form-authoring styles, plus the new signal-based forms:
- Reactive forms — explicit form-model objects in code. The most-used style in production apps.
FormControl,FormGroup,FormArray,FormBuilder, plus the matching directives (formControl,formGroup,formGroupName,formArrayName,formControlName). - Template-driven forms — declarative
[(ngModel)]bindings that lazily build the form model.NgModel,NgForm,NgModelGroup. Lower ceremony for simple forms; less common in large apps. - Signal forms (developer-preview / stabilizing) — a signal-native API in
packages/forms/signals/. Forms become signal trees that integrate with the rest of the signal-based authoring story.
A shared validation system covers all three styles.
Directory layout
packages/forms/
├── src/
│ ├── directives/ # ngForm, ngModel, formGroup, formControl, ...
│ ├── form_providers.ts # provideForms() and the legacy modules
│ ├── model/ # FormControl, FormGroup, FormArray, FormBuilder
│ ├── validators.ts # Built-in Validators (required, email, ...)
│ ├── form_builder.ts # FormBuilder service
│ └── ...
├── signals/ # New signal-based forms API
│ ├── src/
│ └── public_api.ts
├── test/
└── public_api.tsKey abstractions
Reactive forms
| Type | File | What it is |
|---|---|---|
FormControl<T> |
packages/forms/src/model/form_control.ts |
A single field's value, validation, dirty/touched state. Strongly typed. |
FormGroup<T> |
packages/forms/src/model/form_group.ts |
A composite form: a record of named child controls. |
FormArray<T> |
packages/forms/src/model/form_array.ts |
An ordered list of homogeneous controls. |
FormBuilder / NonNullableFormBuilder |
packages/forms/src/form_builder.ts |
Convenience service for building groups/arrays. |
Validators |
packages/forms/src/validators.ts |
Built-in Validators.required, Validators.minLength, ... |
AsyncValidatorFn / ValidatorFn |
same | The function shape validators implement. |
Template-driven forms
| Type | File | What it is |
|---|---|---|
NgModel, NgModelGroup, NgForm |
packages/forms/src/directives/ |
The [(ngModel)] machinery. |
ControlValueAccessor |
packages/forms/src/directives/control_value_accessor.ts |
The bridge between FormControl and a custom input element. |
Signal forms
| Type | File | What it is |
|---|---|---|
form() / signal-form factories |
packages/forms/signals/src/ |
Build a form whose root is a signal-derived tree. |
linkedSignal() integration |
same | Bidirectional binding between a parent state signal and a form field. |
FormField / FormGroup (signal variants) |
same | Signal-typed equivalents of the reactive types. |
Validation flow
graph LR Input["Input event<br/>(keyup, change, input)"] --> CVA["ControlValueAccessor"] CVA --> Control["FormControl.setValue"] Control --> Validators["Run sync validators"] Validators --> Async["Run async validators<br/>(Observable / Promise)"] Async --> State["Update status<br/>(VALID / INVALID / PENDING)"] State --> Notify["Emit on valueChanges + statusChanges"]
Each AbstractControl exposes valueChanges and statusChanges as Observables. Signal forms expose the same data as signals for use in templates and components.
Standalone provider API
bootstrapApplication(App, {
providers: [provideForms()], // For reactive forms
});There's no separate provider for template-driven forms in standalone mode; the directives are simply imported from @angular/forms and used.
ReactiveFormsModule and FormsModule continue to work for NgModule-based apps.
Integration points
@angular/common—NgClass/NgStylework with form-control state classes (ng-valid,ng-invalid,ng-touched, etc.).- Custom inputs — implement
ControlValueAccessorto plug a custom widget into either reactive or template-driven forms. - Async validators — return
Observables that complete withnull(valid) orValidationErrors. RxJS interop is the same as in any Angular service. - Signals — signal forms integrate with the rest of the signal-authoring story (
input(),model(),viewChild()).
Migrations
packages/forms/schematics/ ships migrations for:
- Strongly-typed reactive forms migration (the v14 break).
- Signal forms adoption helpers (when promoted to stable).
Entry points for modification
- A new built-in validator: add it to
packages/forms/src/validators.ts, export frompublic_api.ts, add tests, add a JSDoc example. - A new control type: extend
packages/forms/src/model/with the new class, mirror it in the typings, and add aFormBuildershorthand if appropriate. - Signal forms work: see the
reference-signal-formsproject skill — it documents the mental model in detail. Open via the Skill tool.
Testing
Forms tests run under both browser and node runners. The recommended pattern:
const fb = TestBed.inject(FormBuilder);
const form = fb.group({ name: fb.control('', Validators.required) });
// Act
form.controls.name.setValue('Alice');
// Wait
await Promise.resolve(); // valueChanges is sync
// Assert
expect(form.valid).toBe(true);For UI-binding tests, use the Act-Wait-Assert pattern documented in how-to-contribute/testing.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.