Angular IDPStrong Junior
Модулі / Форми / Стани контролю
🔥 0

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

Стани контролю

Найпоширеніша помилка у формах — показати помилку не тоді. Червоне «поле обовʼязкове» під порожнім полем, до якого користувач ще не дійшов, дратує сильніше, ніж відсутність валідації взагалі. Стани контролю саме про те, коли говорити.

Чотири пари станів

СтанПротилежнийЩо означає
toucheduntouchedКористувач заходив у поле й вийшов із нього
dirtypristineЗначення змінювали
validinvalidВалідатори пройдені
enableddisabledПоле активне
pendingАсинхронна перевірка триває

Ключова різниця, яку плутають: touched — про увагу, dirty — про зміну. Можна зайти в поле й вийти, нічого не ввівши: воно стане touched, але лишиться pristine.

Коли показувати помилку

// стандартна умова, до якої зводиться майже все
const showError = control.invalid && (control.touched || submitted);
форма відкрилась поле порожнє, помилки НЕ видно зайшов і вийшов touched = true ось тепер показуємо ввів коректне valid = true помилка зникає одразу Виняток один: після натискання «Зберегти» показуємо всі помилки, навіть у полях, куди користувач не заходив — інакше він не зрозуміє, чому форма не відправляється.
Помилку показують після того, як користувач мав шанс заповнити поле — або після спроби відправити форму.

Позначити все при відправці

save(): void {
  if (this.form.invalid) {
    this.form.markAllAsTouched();     // показати всі помилки одразу
    this.focusFirstInvalid();         // і перевести фокус до першої
    return;
  }
  this.api.create(this.form.getRawValue());
}

private focusFirstInvalid(): void {
  const el = this.host.nativeElement.querySelector('.ng-invalid[formControlName]');
  (el as HTMLElement | null)?.focus();
}

Перенесення фокуса — маленька деталь, яка сильно допомагає у довгих формах: користувач не мусить шукати очима, де саме проблема. У модулі 7 ми повернемось до цього як до вимоги доступності.

Класи, які Angular вішає сам

.ng-untouched  .ng-touched
.ng-pristine   .ng-dirty
.ng-valid      .ng-invalid
.ng-pending
/* стилізувати можна прямо ними, без жодного коду в класі */
input.ng-invalid.ng-touched {
  border-color: var(--color-danger);
}

input.ng-pending {
  background-image: url('…');   /* індикатор перевірки */
}

Комбінація .ng-invalid.ng-touched — це рівно та сама умова показу помилки, тільки на рівні CSS. Для рамки поля цього достатньо, і тоді в шаблоні лишається тільки текст повідомлення.

Скидання форми

this.form.reset();                       // значення й стани в початкові
this.form.reset({ status: 'todo' });     // зі значеннями за замовчуванням

this.form.markAsPristine();              // «вважати незміненою» без зміни значень
this.form.markAsUntouched();
Після успішного збереження

Якщо форма лишається відкритою, після збереження виклич markAsPristine(). Інакше dirty залишиться true, і guard про незбережені зміни з модуля 2 попередить про втрату даних, яких насправді вже немає. Це та деталь, що звʼязує два модулі докупи.

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