Модуль 6 · урок 12 з 12
Практика модуля
Практика модуля: таблиця з модуля 5 отримує кнопки «Створити» і «Редагувати», а застосунок стає повноцінним CRUD. Це найпомітніша для користувача частина проєкту — і та, де найлегше зробити дрібні помилки, які видно одразу.
КРОК 1Типізована форма
Опиши форму через fb.nonNullable.group. Тип значення має точно збігатися
з типом DTO для створення — перевір це, присвоївши getRawValue() у змінну
типу NewTask. Жодного as.
КРОК 2Свої валідатори
Мінімум два: формат коду й щось змістовне для твого домену. Обидва — чисті функції,
які повертають null для порожнього значення. Плюс один валідатор рівня групи
на два повʼязані поля (наприклад, діапазон дат).
КРОК 3Асинхронна перевірка
Перевірка унікальності коду проти мок-сервісу з модуля 4. Обовʼязково:
take(1), виняток для поточного значення при редагуванні,
catchError і updateOn: 'blur'. Покажи стан «Перевіряємо…»
і врахуй form.pending у кнопці.
КРОК 4Динамічні правила
Хоча б одне правило, що залежить від значення іншого поля: наприклад, при статусі
«заблоковано» причина стає обовʼязковою. Не забудь startWith при підписці
й updateValueAndValidity() після зміни валідаторів.
КРОК 5Компонент помилки
Один app-field-error на всю форму: словник повідомлень, пріоритет,
показ лише при touched або після submit. Звʼязок через
aria-describedby й aria-invalid. Повідомлення — людською мовою
зі зразком, а не «невірне значення».
КРОК 6Модалка
MatDialog із типізованими даними й результатом. Перехопи всі три способи
закриття для перевірки незбережених змін. Фокус у перше поле при відкритті й повернення
на кнопку після закриття. Після успішного збереження — markAsPristine(),
закриття з результатом і перезавантаження списку.
КРОК 7Обробка помилок збереження
409 від сервера про зайнятий код — на поле коду через setErrors.
Інші помилки — загальним повідомленням у модалці. Кнопка блокується під час запиту,
а сам запит іде через exhaustMap, щоб подвійний клік не створив два записи.
КРОК 8FormArray
Додай список підзадач або тегів: додавання, видалення, валідація елементів
і масиву цілком. track ctrl, а не track $index.
Перевір заповнення з даних: clear() перед push.
- Форма повністю типізована; значення збігається з DTO без
as. - Є власні синхронні валідатори, валідатор групи й асинхронна перевірка унікальності.
- Асинхронний валідатор завершується; кнопка враховує
pending. - Правила змінюються залежно від стану сутності.
- Помилки показуються після
touchedабо submit, по одній, людською мовою. - Модалка не втрачає зміни при жодному зі способів закриття.
- Помилка 409 показується на потрібному полі.
- Створення й редагування працюють проти мок-сервісу, список оновлюється.
Що сказати ліду на демо
«Форма типізована через fb.nonNullable, і її значення присвоюється в тип DTO
без жодного as — тож нове поле в моделі одразу підсвітить форму.
Валідатори — чисті функції, які повертають null для порожнього значення,
бо обовʼязковість це справа required. Перевірка унікальності асинхронна,
з updateOn: blur і take(1), з винятком для поточного коду при
редагуванні. Помилки показує один компонент за пріоритетом, звʼязаний через
aria-describedby. У модалці перехоплені всі три способи закриття, тож
незбережені зміни не втрачаються, а 409 від сервера лягає на поле коду, а не в загальний
тост.»
Далі — модуль 7. Він короткий і приємний: стани інтерфейсу й доступність. Скелетони, порожні стани, обробка помилок і клавіатурна навігація. Багато з цього ти вже зробив по дорозі — лишиться довести до ладу й перевірити.