Ось готовий урок, створений за твоїм майстер-промптом.
🎓 Тема: Structural Directives (ngIf, ngFor, *ngSwitch)
(Стиль: David Malan / CS50)
1. 🔥 Вступ: Чому ми не показуємо все й одразу?
Уявіть, що ви зайшли на свій улюблений сайт — скажімо, інтернет-магазин чи соціальну мережу. Але замість звичної стрічки новин ви бачите абсолютно все, що є в коді сайту.
Ви бачите кнопку «Вийти», хоча ви навіть не увійшли. Ви бачите повідомлення «Ваш кошик порожній» і одночасно список товарів у кошику. Ви бачите панель адміністратора, хоча ви звичайний користувач.
Це був би хаос, правда? 🤯
У реальному житті, коли ви приходите в ресторан, офіціант не приносить вам одразу всі страви з меню на стіл, щоб ви вибрали. Він приносить меню (список), а страва з'являється на столі тільки якщо ви її замовили.
У веб-розробці ми маємо таку ж задачу. Нам потрібен механізм, який скаже HTML-сторінці: 1. Цей блок покажи, тільки якщо користувач залогінився. 2. Цей список товарів повтори стільки разів, скільки у нас є товарів у базі.
Без цього наші додатки були б статичними, нудними та перевантаженими. Саме тут на сцену виходять Структурні Директиви. Це інструменти Angular, які дозволяють нам бути архітекторами нашої сторінки в реальному часі.
2. 🧠 Теоретична база: Як це працює «під капотом»?
Давайте розберемося. Що таке директива? Грубо кажучи, це команда для Angular зробити щось з елементом DOM (частиною вашої сторінки).
Але чому вони називаються структурними? Тому що вони змінюють структуру DOM-дерева. Вони фізично додають або видаляють елементи з HTML, а не просто ховають їх.
Свята трійця, яку треба знати:
*ngIf— "Я існую, тільки якщо умова істинна (true)".*ngFor— "Я розмножусь стільки разів, скільки елементів у списку".*ngSwitch— "Я виберу один варіант із багатьох (як перемикач)".
👀 Зверніть увагу на зірочку
*перед назвою! Це не для краси. Це синтаксичний цукор. Вона каже Angular: "Ей, друже, тут буде змінюватися структура шаблону, будь уважний!". Без зірочки це працювати не буде (або працюватиме зовсім інакше).
Як це працює під капотом?
Коли ви пишете <div *ngIf="false">...</div>, Angular не просто робить цьому блоку CSS-стиль display: none. Ні! Він повністю вирізає цей шматок коду з пам'яті браузера. Його там немає. Коли умова стає true, Angular створює його заново. Це важливо для продуктивності.
3. 🧪 Приклади: Від простого до реального
Приклад №1: *ngIf — Охоронець клубу
Уявіть, що у нас є змінна isLoggedIn = false.
<!-- Що ви очікуєте побачити на екрані? -->
<button *ngIf="!isLoggedIn">Увійти</button>
<button *ngIf="isLoggedIn">Вийти</button>
Результат: Ви побачите тільки кнопку "Увійти". Кнопки "Вийти" в HTML-коді сторінки навіть не існує. Якщо ми змінимо isLoggedIn = true, перша кнопка зникне (знищиться), а друга з'явиться.
Приклад №2: *ngFor — Список завдань
У нас є масив у компоненті:
tasks = ['Купити хліб', 'Вивчити Angular', 'Поспати']
<ul>
<!-- Angular, пройдись по tasks і для кожного item створи <li> -->
<li *ngFor="let item of tasks">
{{ item }}
</li>
</ul>
Що тут відбувається?
let item — це ми створюємо локальну змінну для кожного обертання циклу. Ми могли назвати її let task, let x або let pizza.
Angular бере шаблон <li>...</li> і штампує його 3 рази.
Приклад №3: *ngSwitch — Світлофор
У нас є змінна color = 'yellow'.
<div [ngSwitch]="color">
<p *ngSwitchCase="'red'">🔴 Стій!</p>
<p *ngSwitchCase="'yellow'">🟡 Готуйся...</p>
<p *ngSwitchCase="'green'">🟢 Їдь!</p>
<p *ngSwitchDefault>⚫ Світлофор зламався</p>
</div>
Результат: На екрані буде тільки "🟡 Готуйся...".
Зверніть увагу: на самому контейнері [ngSwitch] зірочки немає (це атрибут), а на варіантах *ngSwitchCase — є (бо вони додаються/видаляються).
4. 🛠 Практична частина
Час забруднити руки кодом! Відкривайте свій редактор.
🔹 Завдання 1: "Привид"
Створіть параграф <p>, який містить секретний текст. Додайте кнопку "Показати секрет".
* Використовуйте змінну isVisible: boolean.
* При кліку змінюйте її значення (toggle).
* Використовуйте *ngIf на параграфі.
🔹 Завдання 2: "Список покупок"
У вашому компоненті створіть масив об'єктів:
products = [{name: 'Apple', price: 20}, {name: 'Banana', price: 10}, {name: 'Audi', price: 50000}]
* Виведіть їх список через *ngFor.
* Показуйте назву і ціну.
🔹 Завдання 3: "Тільки для багатих" (Комбінація)
Використовуючи попередній список:
* Додайте всередині циклу *ngFor умову *ngIf.
* Якщо ціна товару більше 1000 — додайте поруч емодзі 💎 (діамант) або напис "VIP".
🔹 Завдання 4: Міні-кейс "Статус замовлення"
У вас є змінна status, яка може бути: 'pending', 'shipped', 'delivered', 'error'.
Використовуючи *ngSwitch, виведіть повідомлення різного кольору для кожного статусу.
* Pending -> "Очікуємо" (жовтий)
* Shipped -> "В дорозі" (синій)
* Delivered -> "Доставлено" (зелений)
* Error -> "Помилка" (червоний)
🔹 Питання "А що, якщо..."
А що, якщо масив products порожній ([])? Що покаже *ngFor? (Спробуйте і переконайтесь, що нічого не зламається, просто буде порожньо). Як додати повідомлення "Список порожній", використовуючи *ngIf та products.length?
5. 💡 Мислення як у розробника
Ви вже майже профі, але є кілька граблів, на які наступають усі новачки. Давайте їх оминемо.
❌ Помилка №1: Два капітани на одному кораблі
Новачки часто намагаються написати так:
<div *ngIf="isVisible" *ngFor="let item of items">...</div>
Angular скаже: "Error!". Не можна вішати дві структурні директиви на один елемент. Він не знає, що робити першим: перевіряти умову чи крутити цикл?
✅ Як думає профі:
Він використовує обгортку. А ще краще — «невидиму» обгортку <ng-container>:
<ng-container *ngIf="isVisible">
<div *ngFor="let item of items">...</div>
</ng-container>
<ng-container> не створює зайвого <div> у вашому HTML, він просто групує логіку.
❌ Помилка №2: *ngIf vs [hidden]
Можна сховати елемент через [hidden]="!isVisible". Це просто змінить CSS на display: none.
* Якщо елемент "важкий" (графік, карта, відео) — краще *ngIf (повністю знищує, звільняє пам'ять).
* Якщо елемент треба показати/сховати миттєво і часто (наприклад, випадаюче меню) — іноді [hidden] краще, бо браузеру не треба перемальовувати його з нуля.
🚀 Порада з практики: index
Іноді в циклі треба знати порядковий номер елемента. *ngFor дає нам бонус:
<div *ngFor="let item of items; let i = index"> {{ i + 1 }}. {{ item }} </div>
Завжди пам'ятайте про цей інструмент, коли треба нумерація!
6. 🧩 Підсумок
Отже, що ми сьогодні поклали у свій інструментарій?
- Ми навчилися керувати реальністю на сторінці: створювати та знищувати елементи за умовою (
*ngIf). - Ми навчилися масштабувати контент: перетворювати масиви даних на списки HTML (
*ngFor). - Ми навчилися перемикати варіанти відображення (
*ngSwitch).
Тепер ви можете перетворити "сухий" масив даних на живий інтерактивний каталог товарів або список друзів.
Що далі?
Уявіть, що ціна товару у вас 20, а ви хочете показати $20.00 або 20 ₴. Або ви хочете дату 2023-10-05 показати як "5 жовтня". Невже треба писати складні функції вручну?
Ні! Наступного разу ми поговоримо про Pipes (Пайпи) — магічні фільтри для трансформації даних прямо в шаблоні.
А поки — вперед кодити! 💻🚀