angular-forms
SKILL.md
When to Use What
| Use Case | Recommendation |
|---|---|
| New apps with signals | Signal Forms (experimental) |
| Production apps | Reactive Forms |
| Simple forms | Template-driven |
Signal Forms (v21+, experimental)
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();
}
}
}
Signal Forms Benefits
- Automatic two-way binding
- Type-safe field access
- Schema-based validation
- Built on signals
Reactive Forms (production)
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();
}
}
}
Key Points
- ALWAYS use
fb.nonNullable.group()for type safety - Use
getRawValue()to get typed values - Reactive Forms are synchronous (easier to test)
Nested Forms & FormArray
form = 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(''));
}
Resources
Weekly Installs
6
Repository
gentleman-programming/gentleman-skillsFirst Seen
2 days ago
Installed on
claude-code5
windsurf3
opencode3
codex3
antigravity3
gemini-cli3