Open-Source Wikis

/

Angular

/

Packages

/

@angular/forms

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:

  1. 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).
  2. 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.
  3. 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.ts

Key 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/commonNgClass / NgStyle work with form-control state classes (ng-valid, ng-invalid, ng-touched, etc.).
  • Custom inputs — implement ControlValueAccessor to plug a custom widget into either reactive or template-driven forms.
  • Async validators — return Observables that complete with null (valid) or ValidationErrors. 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 from public_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 a FormBuilder shorthand if appropriate.
  • Signal forms work: see the reference-signal-forms project 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.

@angular/forms – Angular wiki | Factory