Angular IDPStrong Junior
🔥 0

Модуль 2 · урок 15 з 15

Практика модуля

Одна робота, яка закриває всі критерії другої цілі. Тут ти вперше піднімеш реальний Angular-проєкт і перенесеш у нього те, що зверстав у модулі 1. Це найдовша практика в плані — розрахована на кілька вечорів, і поспішати не треба.

Що має вийти

Каркас застосунку: три екрани, навігація між ними, захищена адмінка, типізовані моделі й нуль any. Даних поки що немає — вони зʼявляться в модулі 4, тому все, що потрібно, це кілька захардкоджених обʼєктів.

КРОК 1Підняти проєкт

Створи проєкт через CLI зі SCSS. Перевір, що strict і strictTemplates увімкнені. Заведи структуру папок core, shared, features. Перенеси токени й скидання стилів із модуля 1 у src/styles/.

Коміт: chore: bootstrap project with strict mode.

КРОК 2Каркас із модуля 1 у компонентах

Розбий свою розмітку на компоненти: app-header, app-sidebar, і кореневий шаблон із <router-outlet /> усередині робочої області. Перемикач теми переїжджає в app-header. Усім компонентам одразу постав ChangeDetectionStrategy.OnPush і :host { display: block } там, де потрібні розміри.

КРОК 3Моделі й типи

Опиши свої сутності в core/models/: базовий інтерфейс, статус як union із as const, і похідні типи через utility types — окремо для створення (Omit), окремо для оновлення (Partial), окремо для рядка списку (Pick). Додай Record зі словником підписів статусів.

Тут же — DTO і функція-мапер, навіть якщо поки що вони однакові: у модулі 4 це заощадить час.

КРОК 4Роутинг

Три маршрути через loadComponent: список, деталі з параметром :id, адмінка. Плюс редірект із порожнього шляху й сторінка 404 на '**'. Увімкни withComponentInputBinding() і прийми id як input.required. У сайдбарі — routerLink із routerLinkActive.

КРОК 5Сервіс і DI

Зроби сервіс із providedIn: 'root', який тримає масив захардкоджених сутностей у сигналі й уміє їх віддавати, додавати й оновлювати. Компоненти отримують його через inject(). Заведи InjectionToken для конфігу (наприклад, розмір сторінки) і використай його хоча б в одному місці.

КРОК 6Два guards

CanActivate: адмінка доступна лише з потрібною роллю. Роль поки що з простого сервісу з сигналом — перемикається кнопкою в шапці, щоб було що показати. При відмові — createUrlTree на сторінку «немає доступу».

CanDeactivate: на екрані з формою (нехай поки що це просто <input> з сигналом) — попередження про незбережені зміни через інтерфейс HasUnsavedChanges.

Логіку рішення винеси в чисті функції — у модулі 8 ти їх протестуєш.

КРОК 7Пайп і директива

Пайп: форматування, яке реально потрібне на екрані — відносна дата, тривалість або підпис статусу. Директива: підсвітка рядків за умовою, автофокус або приховування за роллю. Обидва мають використовуватись у шаблоні, а не лежати «для галочки».

КРОК 8ESLint і нуль any

Додай @angular/eslint, постав no-explicit-any у error і prefer-on-push-component-change-detection. Прожени ng lint і почисти все, що знайде. Якщо десь без any ніяк — локальний disable із коментарем, чому.

Модуль зараховано, якщо
  • Проєкт на Angular CLI зі strict, у коді рівно нуль any, ng lint зелений.
  • Працюють два guards: за роллю й на незбережені зміни.
  • Є власні пайп і директива, і вони реально використовуються.
  • Моделі побудовані з однієї базової через generics і utility types.
  • Усі екрани підключені через loadComponent.
  • Усі компоненти на OnPush.

Що сказати ліду на демо

«Проєкт на strict, лінтер валить збірку на будь-якому any — довелось скрізь писати чесні типи, зокрема unknown із type guard там, де дані приходять ззовні. Моделі виведені з однієї базової через Pick, Omit і Partial, тому нове поле не треба дописувати в пʼяти місцях. Guards функціональні: за роллю повертає UrlTree, щоб не було двох навігацій одночасно, а CanDeactivate типізований через інтерфейс, тож працює з будь-яким компонентом із незбереженими змінами. Логіку рішень винесено в чисті функції — їх зручно тестувати.»

Скільки це реально займе

Кроки 1–4 — один-два вечори. Кроки 5–6 — ще два, і саме там буде найбільше нового. Кроки 7–8 — один. Якщо застрягаєш більш ніж на годину в одному місці — це сигнал не «я не розумію», а «варто відкласти й повернутись завтра»: конкретно в DI та guards друга спроба зазвичай коротша за першу.

Далі — модуль 3. Там ти доведеш каркас до вигляду справжнього дашборду й розберешся, як Angular вирішує, що саме перемальовувати. Після цього — модуль 4 із RxJS, і застосунок нарешті отримає дані.