Ось готовий урок, згенерований за твоїм майстер-промптом.
🎓 Урок: Форми в Angular (Template-driven Forms)
Привіт, друзі! 👋 Це CS50... тобто, це наш курс з Angular!
Сьогодні ми розберемо тему, без якої будь-який веб-додаток залишається просто красивою картинкою. Ми поговоримо про Template-driven Forms.
1. 🔥 Вступ: Проблема та мотивація
Уявіть, що ви прийшли до банку, щоб відкрити рахунок. Але замість того, щоб дати вам бланк і ручку, клерк просто мовчки дивиться на вас. Ви намагаєтеся щось сказати, а він вас не чує. Дивно, правда?
Веб-сайт без форм — це саме такий "глухий" клерк. Ви бачите інформацію, але не можете нічого передати назад.
- Як користувач має ввести свій логін?
- Як клієнт замовить піцу з подвійним сиром?
- Як ви відправите коментар під цим уроком?
Без форм інтернет був би просто набором цифрових газет. Нам потрібен діалог. Нам потрібно, щоб користувач міг ввести дані, а ми — їх схопити, перевірити та відправити на сервер.
В Angular є два шляхи це зробити. Сьогодні ми йдемо шляхом найменшого опору — Template-driven Forms.
Аналогія: Уявіть, що HTML-шаблон — це ваш бланк замовлення в ресторані. Ви (розробник) просто розмічаєте на папері: "Тут напиши страву", "Тут постав галочку, якщо з собою". Ви не наймаєте окремого менеджера (TypeScript-код), щоб стежити за кожною літерою, яку пише клієнт. Бланк (Template) сам керує процесом. Angular просто дивиться на цей бланк і робить магію.
2. 🧠 Теоретична база (Що "під капотом")
Давайте розберемося, як це працює, не засинаючи над документацією.
У Template-driven підході головним босом є HTML. Майже вся логіка (валідація, прив’язка даних) пишеться прямо в тегах.
🔑 Три кити, на яких це тримається:
FormsModule: Це як вмикач електрики для форм. Якщо ви не підключите цей модуль уapp.module.ts(або уimportsвашого standalone компонента), Angular просто ігноруватиме ваші спроби створити форму.ngForm: Як тільки Angular бачить тег<form>, він автоматично (тихо і непомітно) створює об'єктngForm. Це "душа" вашої форми. Вона знає все: чи валідна форма, чи користувач щось змінював, і які там дані.[(ngModel)]: Знаменитий "банан у коробці" 🍌📦. Це двосторонній зв'язок.- Змінили змінну в коді -> змінилося значення в інпуті.
- Написали щось в інпуті -> змінилася змінна в коді.
⚙️ Як це працює під капотом?
Коли ви додаєте директиву ngModel до звичайного <input>, Angular каже: "Ага! Ти хочеш, щоб я стежив за цим полем". Він створює екземпляр FormControl (контролер) для цього конкретного поля і прив'язує його до вашої змінної. Він слухає кожне натискання клавіші і миттєво оновлює дані.
Що треба запам'ятати залізно:
У Template-driven формах, якщо ви використовуєте
ngModelу тегу<form>, ви обов'язково маєте додати атрибутname="...". Без імені Angular не знатиме, як назвати цю властивість у загальному об'єкті форми.
3. 🧪 Приклади (від простого до реального)
Приклад №1: Найпростіший інпут
У нас є змінна userName = 'David'. Ми хочемо її редагувати.
Що ви очікуєте побачити в коді? Просто HTML і змінну.
// component.ts
export class UserComponent {
userName: string = 'David';
}
<!-- component.html -->
<label>Ім'я:</label>
<!-- Банан у коробці -->
<input [(ngModel)]="userName" type="text">
<p>Привіт, {{ userName }}!</p>
Що відбувається: Ви друкуєте в полі, і текст у параграфі <p> змінюється миттєво. Магія синхронізації.
Приклад №2: Повноцінна форма логіну
А тепер реальне життя. Нам треба логін і пароль. І нам треба "спіймати" момент відправки форми.
Питання до вас: як ми отримаємо доступ до всієї форми, щоб перевірити, чи вона валідна?
Відповідь: Використовуємо Template Reference Variable (змінну шаблону) — #loginForm.
// login.component.ts
export class LoginComponent {
user = {
email: '',
password: ''
};
onSubmit(form: any) {
console.log('Дані форми:', form.value);
console.log('Чи валідна форма?', form.valid);
}
}
<!-- login.component.html -->
<!-- Створюємо посилання #myForm на директиву ngForm -->
<form #myForm="ngForm" (ngSubmit)="onSubmit(myForm)">
<div>
<label>Email:</label>
<!-- name="email" ОБОВ'ЯЗКОВО! -->
<input
type="email"
name="email"
[(ngModel)]="user.email"
required
email>
</div>
<div>
<label>Password:</label>
<input
type="password"
name="password"
[(ngModel)]="user.password"
required
minlength="6">
</div>
<!-- Кнопка блокується, якщо форма не валідна -->
<button type="submit" [disabled]="!myForm.valid">Увійти</button>
</form>
Розбір польотів:
1. #myForm="ngForm": Ми дали ім'я всій формі, щоб звертатися до неї в HTML (наприклад, для кнопки disabled).
2. required, email, minlength: Це звичайні HTML5 атрибути, але Angular їх "розуміє" і використовує для валідації.
3. Якщо ви введете "abc" у поле email, myForm.valid стане false, і кнопка вимкнеться.
4. 🛠 Практична частина
Час забруднити руки кодом! Відкривайте IDE або StackBlitz.
Завдання 1: "Дзеркало"
Створіть інпут і заголовок <h1>. Зробіть так, щоб текст, який ви вводите в інпут, одразу ставав заголовком сторінки.
Завдання 2: "Забудько"
Візьміть приклад №2 (Логін). Видаліть атрибут name="email" з першого інпуту. Запустіть код. Відкрийте консоль браузера.
Що ви бачите? (Спойлер: Angular буде сваритися червоним текстом. Прочитайте помилку і зрозумійте її).
Завдання 3: "Чекбокс долі" Додайте до форми чекбокс "Я погоджуюсь з правилами". Зробіть так, щоб кнопка "Відправити" була активною тільки тоді, коли чекбокс натиснутий (навіть якщо інші поля заповнені вірно).
Завдання 4: Міні-кейс "Список покупок"
Створіть просту форму з одним полем "Продукт" і кнопкою "Додати".
1. Коли користувач тисне "Додати", продукт має падати в масив products і відображатися списком <ul> знизу.
2. Важливо: Після додавання поле вводу має очиститися!
Завдання 5: "А що, якщо..."
Що буде, якщо використати [ngModel] (без дужок) замість [(ngModel)]?
Спробуйте. Введіть значення в інпут. Чи зміниться змінна в компоненті? Чому? (Це називається одностороння прив'язка).
5. 💡 Мислення як у розробника
Коли ви працюєте з формами, легко потрапити в пастку. Ось як мислять досвідчені Angular-розробники:
-
Помилка новачка: Забути
FormsModule.- Симптом: Ви пишете
[(ngModel)], а консоль кричить: "Can't bind to 'ngModel' since it isn't a known property of 'input'". - Рішення: Біжіть в модуль і імпортуйте його. Це класика, всі через це проходили.
- Симптом: Ви пишете
-
Про "Спагетті-код" в HTML:
- Template-driven форми класні, бо прості. Але якщо ви бачите, що у вашому HTML куча умов
*ngIf, складні перевірки валідації на 5 рядків — зупиніться. - Думка сеньйора: "Тут стає занадто складно для шаблону. Можливо, час переходити на Reactive Forms або винести логіку в TypeScript".
- Template-driven форми класні, бо прості. Але якщо ви бачите, що у вашому HTML куча умов
-
Візуальний зворотний зв'язок (UX):
- Користувачі ненавидять, коли форма червоніє ще до того, як вони почали писати.
- Використовуйте властивості
touched(користувач торкнувся поля) іdirty(користувач змінив значення). - Правило: Показуйте помилку "Email некоректний" тільки якщо
email.invalid && email.touched. Не лякайте людей одразу!
6. 🧩 Підсумок
Отже, що ми маємо на виході?
- Ви знаєте, як створити форму, не пишучи купу коду в класі.
- Ви вмієте використовувати "банан у коробці"
[(ngModel)]для зв'язку даних. - Ви зрозуміли, що
<form>в Angular — це живий організм, який знає про свій стан (валідний він чи ні). - Ви пам'ятаєте про атрибут
name, без якого магія не працює.
Ви тепер вмієте: Робити прості форми реєстрації, пошуку, зворотного зв'язку за 5 хвилин.
🤔 Тизер: Але уявіть ситуацію: вам треба зробити форму, де поля додаються динамічно (наприклад, кнопка "Додати ще одного пасажира"). Або вам треба перевіряти, чи такий email вже існує в базі даних поки користувач друкує. Робити це в шаблоні — пекло. Для таких задач "з зірочкою" Angular має потужну зброю — Reactive Forms. І саме про це ми поговоримо наступного разу.
А поки — кодьте і не забувайте закривати теги! Це був CS50! 👨💻🚀