We use cookies to enhance your experience on the site
CodeWorlds

Forms in Angular - The Art of Calligraphy

Forms in Angular are like the art of calligraphy - they require precision, elegance, and offer two main approaches. Every brush stroke (form field) must be accurate!

Two Approaches to Forms

Template-driven Forms

  • Declarative, in the HTML template
  • Simpler, less TypeScript code
  • Good for simple forms

Reactive Forms (Recommended)

  • Programmatic, in the TypeScript code
  • Full control and testability
  • Better for complex forms

Reactive Forms - Basics

1import { Component, inject } from '@angular/core';
2import { ReactiveFormsModule, FormBuilder, FormGroup, Validators } from '@angular/forms';
3
4@Component({
5  selector: 'app-samurai-form',
6  standalone: true,
7  imports: [ReactiveFormsModule],
8  template: \`
9    <form [formGroup]="samuraiForm" (ngSubmit)="onSubmit()">
10      <div class="field">
11        <label for="name">Samurai Name</label>
12        <input id="name" formControlName="name" placeholder="Musashi">
13        @if (samuraiForm.get('name')?.errors?.['required'] &&
14             samuraiForm.get('name')?.touched) {
15          <span class="error">Name is required</span>
16        }
17        @if (samuraiForm.get('name')?.errors?.['minlength']) {
18          <span class="error">Minimum 2 characters</span>
19        }
20      </div>
21
22      <div class="field">
23        <label for="level">Level</label>
24        <input id="level" formControlName="level" type="number">
25        @if (samuraiForm.get('level')?.errors?.['min']) {
26          <span class="error">Minimum level 1</span>
27        }
28      </div>
29
30      <div class="field">
31        <label for="clan">Clan</label>
32        <select id="clan" formControlName="clan">
33          <option value="">Select a clan</option>
34          <option value="tokugawa">Tokugawa</option>
35          <option value="oda">Oda</option>
36          <option value="takeda">Takeda</option>
37        </select>
38      </div>
39
40      <button type="submit" [disabled]="samuraiForm.invalid">
41        Save Samurai
42      </button>
43
44      <p>Status: {{ samuraiForm.valid ? 'Valid' : 'Invalid' }}</p>
45    </form>
46  \`
47})
48export class SamuraiFormComponent {
49  private fb = inject(FormBuilder);
50
51  samuraiForm = this.fb.group({
52    name: ['', [Validators.required, Validators.minLength(2)]],
53    level: [1, [Validators.required, Validators.min(1), Validators.max(100)]],
54    clan: ['']
55  });
56
57  onSubmit(): void {
58    if (this.samuraiForm.valid) {
59      console.log('Samurai data:', this.samuraiForm.value);
60      // { name: 'Musashi', level: 10, clan: 'tokugawa' }
61    }
62  }
63}
Go to CodeWorlds