Angular forms: Signal Forms (experimental) and Reactive Forms. Trigger: When working with forms, validation, or form state in Angular.
67
80%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
Fix and improve this skill with Tessl
tessl review fix ./curated/angular/forms/SKILL.md| Use Case | Recommendation |
|---|---|
| New apps with signals | Signal Forms (experimental) |
| Production apps | Reactive Forms |
| Simple forms | Template-driven |
import { form, FormField, required, email } from '@angular/forms/signals';
@Component({
imports: [FormField],
template: `
<form>
<input [formField]="emailField" type="email" />
<input [formField]="passwordField" type="password" />
<button (click)="submit()">Login</button>
</form>
`
})
export class LoginComponent {
readonly loginForm = form({
email: ['', [required, email]],
password: ['', required]
});
readonly emailField = this.loginForm.controls.email;
readonly passwordField = this.loginForm.controls.password;
submit() {
if (this.loginForm.valid()) {
const values = this.loginForm.value();
}
}
}import { FormBuilder, Validators, ReactiveFormsModule } from '@angular/forms';
@Component({
imports: [ReactiveFormsModule],
template: `
<form [formGroup]="form" (ngSubmit)="submit()">
<input formControlName="email" type="email" />
<input formControlName="password" type="password" />
<button type="submit" [disabled]="form.invalid">Login</button>
</form>
`
})
export class LoginComponent {
private readonly fb = inject(FormBuilder);
form = this.fb.nonNullable.group({
email: ['', [Validators.required, Validators.email]],
password: ['', [Validators.required, Validators.minLength(8)]],
});
submit() {
if (this.form.valid) {
const { email, password } = this.form.getRawValue();
}
}
}fb.nonNullable.group() for type safetygetRawValue() to get typed valuesform = this.fb.nonNullable.group({
name: [''],
address: this.fb.group({
street: [''],
city: [''],
}),
phones: this.fb.array([this.fb.control('')]),
});
get phones() {
return this.form.get('phones') as FormArray;
}
addPhone() {
this.phones.push(this.fb.control(''));
}c8036a3
Also appears in
since Mar 4, 2026
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.