Angular IDPStrong Junior
Модулі / Форми / Два підходи до форм
🔥 0

Модуль 6 · урок 1 з 12

Два підходи до форм

Форми — друга за частотою задача в ентерпрайзі після таблиць. В Angular їх два види, і вибір між ними — типове питання на співбесіді. Відповідь коротка, але за нею стоїть різниця в тому, де живе стан форми.

Template-driven: стан у шаблоні

<form #f="ngForm" (ngSubmit)="save(f.value)">
  <input name="title" [(ngModel)]="task.title" required minlength="3">
  <button [disabled]="f.invalid">Зберегти</button>
</form>

Angular сам створює контроли, читаючи розмітку. Правила валідації — атрибути. У класі майже нічого немає. Швидко для форми з трьох полів, і рівно тому обмежено: щойно потрібна умовна валідація чи динамічні поля, шаблон перетворюється на кашу з @if.

Reactive: стан у класі

export class TaskForm {
  protected readonly form = new FormGroup({
    title: new FormControl('', { nonNullable: true, validators: [Validators.required] }),
    hours: new FormControl(1, { nonNullable: true }),
  });

  save(): void {
    if (this.form.invalid) return;
    this.api.create(this.form.getRawValue());
  }
}
<form [formGroup]="form" (ngSubmit)="save()">
  <input formControlName="title">
  <input formControlName="hours" type="number">
</form>

Тут форма — це обʼєкт у коді. Шаблон лише привʼязується до вже наявної структури. Звідси й усі переваги: структуру видно в одному місці, її можна типізувати, тестувати, змінювати програмно й підписуватись на зміни через RxJS.

Порівняння

Template-drivenReactive
Де станУ шаблоніУ класі
ТипізаціяПрактично немаєПовна
Динамічні поляВажкоПриродно
Складна валідаціяНезручноПросто
Підписка на зміниЧерез ngModelChangevalueChanges — повноцінний потік
ТестуванняПотрібен шаблонФорму можна створити й перевірити без DOM
Асинхронна валідаціяОбмеженоШтатно
Що вибрати для IDP

У таблиці ліда прямо написано «strongly typed ReactiveFormsModule» — тож вибору немає, і це правильно. Але знати про template-driven варто: на робочих проєктах трапляються обидва, і питання «чим вони відрізняються» звучить майже завжди.

Головна перевага реактивних форм: форма — це потік

this.form.valueChanges.pipe(
  debounceTime(400),
  takeUntilDestroyed(),
).subscribe(value => this.autosave(value));

this.form.controls.status.valueChanges.pipe(
  takeUntilDestroyed(),
).subscribe(status => this.applyRulesFor(status));

this.form.statusChanges.subscribe(s => …);   // VALID | INVALID | PENDING | DISABLED

Уся робота з модуля 4 тут окупається: автозбереження, реакція на зміну одного поля, асинхронна перевірка — усе це звичайні потоки, до яких застосовуються ті самі оператори.

Що знадобиться на екрані з таблицею

Наприкінці модуля в тебе буде модалка створення й редагування запису — з валідацією, перевіркою унікальності коду проти мокованих даних і попередженням про незбережені зміни. Тобто таблиця з модуля 5 нарешті отримає кнопки, і застосунок стане повноцінним CRUD.

≈ 30 хв · +25 XP за урок