no-reactive-forms
Disallow Angular Reactive Forms in favor of Signal Forms.
This rule helps migrate from Angular Reactive Forms to @angular/forms/signals. Reactive Forms require mutable FormControl / FormGroup state that is often shared between components and services, which makes it harder to track where state changes originate. Signal Forms keep form state in Signals, so the dependency graph is explicit and reactive by default.
Use this rule when you want to prevent new Reactive Forms code from being introduced while a project is adopting Signal Forms.
Rule Details
This rule reports three patterns:
-
Named imports of Reactive Forms APIs from
@angular/forms
Any import of the following names is reported:AbstractControl,FormArray,FormArrayName,FormBuilder,FormControl,FormControlDirective,FormControlName,FormGroup,FormGroupDirective,FormGroupName,FormRecord,NonNullableFormBuilder,ReactiveFormsModule,UntypedFormArray,UntypedFormBuilder,UntypedFormControl,UntypedFormGroup,Validators. -
Namespace or default imports from
@angular/forms
import * as forms from '@angular/forms'andimport forms from '@angular/forms'are reported because they can bypass the named-API checks. -
Reactive Forms template bindings
The following bindings are reported in Angular templates:
formControl,formControlName,formGroup,formGroupName,formArrayName.
FormsModule and ngModel are intentionally outside the scope of this rule. Use @rdlabo/rules/no-template-driven-forms to restrict those.
Examples
Incorrect
// TypeScript: importing Reactive Forms APIs
import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
import * as forms from '@angular/forms';
const control = new forms.FormControl('');
<!-- Template: Reactive Forms bindings -->
<form [formGroup]="userForm">
<input formControlName="name" />
</form>
Correct
import { signal } from '@angular/core';
import { form, required } from '@angular/forms/signals';
const userModel = signal({ name: '' });
const userForm = form(userModel, (path) => {
required(path.name);
});
<!-- Template: Signal Forms field binding -->
<input [formField]="userForm.name" />
Options
This rule has no options.
When to enable
Enable this rule in Angular projects that have adopted Signal Forms, or in projects that are migrating away from Reactive Forms. It is safe to enable alongside @rdlabo/rules/no-template-driven-forms to cover both form styles.