Ось готовий урок, створений спеціально для тебе у стилі CS50. Вмикай редактор коду, поїхали!
🎓 УРОК: Two-way Binding та магія [(ngModel)]
Привіт, друзі! 👋 Я радий бачити вас на цій лекції.
Сьогодні ми говоримо про тему, яка перетворює ваші додатки з "німих" статичних сторінок на живі, інтерактивні інтерфейси. Ми розберемо Two-way Binding (двостороннє зв'язування) та директиву ngModel в Angular.
1. 🔥 Вступ: Дзеркало та ефект запізнення
Уявіть, що ви зранку підходите до дзеркала, щоб почистити зуби. Ви відкриваєте рота... а ваше відображення стоїть нерухомо. Ви чекаєте 5 секунд, натискаєте кнопку "Оновити відображення", і тільки тоді дзеркало показує, що ви відкрили рота.
Це було б жахливо, правда?
У веб-розробці часто виникає саме така проблема. У нас є дані (у вашому JavaScript/TypeScript коді) і є відображення (HTML). * Коли ви змінюєте змінну в коді — ви хочете, щоб це миттєво побачив користувач. * Коли користувач щось друкує в полі вводу — ви хочете, щоб ця змінна в коді миттєво оновилася.
Питання до вас: Ви хочете писати десятки рядків коду, щоб вручну відловлювати кожну букву, яку ввів користувач, і переписувати змінну?
Звісно, ні. Саме тут на сцену виходить Two-way Binding. Це механізм, який робить ваш інтерфейс дзеркалом: дані змінюються — картинка оновлюється. Картинка змінюється — дані оновлюються. Миттєво.
2. 🧠 Теоретична база (Що під капотом?)
Давайте заглянемо під капот. В Angular (і багатьох інших фреймворках) є два потоки даних:
- Property Binding
[]: Дані течуть від Коду до HTML (вниз).- Аналогія: Проектор. Комп'ютер показує картинку на екрані.
- Event Binding
(): Дані течуть від HTML до Коду (вгору).- Аналогія: Клавіатура. Ви тиснете клавіші, комп'ютер реагує.
Two-way binding — це поєднання обох цих процесів одночасно.
Синтаксис "Банан у коробці" 🍌📦
В Angular для цього використовується спеціальний синтаксис: [()].
Запам'ятайте цю візуальну аналогію: круглі дужки (банан) всередині квадратних дужок (коробка).
<input [(ngModel)]="userName">
Що відбувається "під капотом"?
Коли ви пишете цей короткий код, Angular насправді розгортає його у щось таке:
- Він бере значення змінної
userNameі записує його вvalueінпута (зв'язування властивості[]). - Він слухає подію
input(коли ви друкуєте). Кожен раз, коли ви натискаєте клавішу, Angular бере нове значення і оновлює зміннуuserName(зв'язування події()).
📌 Що треба запам'ятати залізно: Щоб це запрацювало, ваша змінна в класі (TypeScript) і поле вводу в шаблоні (HTML) стають сіамськими близнюками. Зміниш одного — зміниться й інший.
3. 🧪 Приклади (Coding Time)
Перед тим як почати: переконайтеся, що ви імпортували FormsModule у ваш app.module.ts. Без цього магія не спрацює!
Приклад 1: "Ехо" (Найпростіший)
Очікування: Я хочу писати текст у поле, і щоб він одразу дублювався текстом поруч.
// app.component.ts
export class AppComponent {
title = ''; // Просто пустий рядок
}
<!-- app.component.html -->
<label>Введіть назву статті:</label>
<input [(ngModel)]="title" placeholder="Друкуй тут...">
<h1>Ваш заголовок: {{ title }}</h1>
Результат: Ви пишете "Привіт, світ!", і заголовок <h1> оновлюється синхронно з вашим введенням.
Приклад 2: Логін форма (Реальніший)
Уявіть, що кнопка "Увійти" має бути заблокована, якщо користувач ще нічого не ввів.
export class LoginComponent {
userEmail = '';
}
<input type="email" [(ngModel)]="userEmail" placeholder="Ваш email">
<!-- Кнопка активна тільки якщо userEmail не пустий -->
<button [disabled]="userEmail === ''">Увійти</button>
<p *ngIf="userEmail.length > 0">Ви вводите: {{ userEmail }}</p>
Чому це круто? Нам не треба писати функцію checkIfEmailisEmpty(). Angular сам перевіряє стан змінної userEmail. Якщо вона пуста — кнопка вимкнена. Ви ввели символ — змінна змінилася — кнопка увімкнулася.
4. 🛠 Практична частина
Час розім'яти пальці! Відкривайте IDE.
🔹 Завдання 1: Іменний бейджик Створіть поле вводу для імені. Нижче зробіть прямокутник (div), в якому великими літерами написано: "Привіт, я [ІМ'Я]".
🔹 Завдання 2: Розмір шрифту
Створіть input type="number" і прив'яжіть його до змінної fontSize. Нижче створіть текст, розмір якого (style.fontSize.px) залежить від цього числа.
Челендж: Зробіть так, щоб текст ріс, коли ви крутите число в інпуті.
🔹 Завдання 3: Чекбокс згоди
Створіть змінну isAgreed = false. Додайте чекбокс <input type="checkbox"> з ngModel. Зробіть кнопку "Відправити", яка зникає, якщо галочка не стоїть.
🔹 Питання "А що, якщо...":
Що станеться, якщо у компоненті (TypeScript) ви напишете name = 'David', а в HTML в інпуті користувач зітре це і напише 'Oleg'? Яке значення буде в змінній name в цей момент?
5. 💡 Мислення як у розробника
Ось де новачки часто помиляються, а профі діють обережно.
❌ Помилка новачка: "Забутий модуль"
Ви написали код, запускаєте, а в консолі червоним: Can't bind to 'ngModel' since it isn't a known property of 'input'.
Діагноз: Ви забули додати FormsModule в imports у вашому app.module.ts. Це класика. Не панікуйте, просто імпортуйте.
❌ Помилка новачка: "Надмірне використання"
Не пхайте [(ngModel)] туди, де він не потрібен. Якщо вам треба просто показати дані і ніколи їх не змінювати з інтерфейсу — використовуйте просту інтерполяцію {{ value }}. ngModel "важчий", бо він створює слухачі подій.
🧠 Як думає профі:
Досвідчений розробник розуміє: Two-way binding — це зручно для простих форм. Але якщо форма величезна і складна (50 полів, валідація, залежності), він перейде на Reactive Forms (це ми вивчимо пізніше). Але для швидких задач, перемикачів, пошукових рядків — ngModel це найкращий інструмент.
6. 🧩 Підсумок
Отже, що ми сьогодні поклали у свою валізу знань:
- Двостороннє зв'язування — це синхронізація даних між TS і HTML в реальному часі.
- Синтаксис — "Банан у коробці"
[(ngModel)]. - Використання — Ідеально для полів вводу (input, select, textarea, checkbox).
- Умова — Потрібен
FormsModule.
Тепер ви вмієте створювати інтерфейси, які "відчувають" користувача миттєво.
🚀 Тизер наступного уроку:
А що, як нам треба показати не одне ім'я, а список із 100 студентів? Копіювати 100 разів тег <div>? Ні! На наступному уроці ми познайомимося з Структурними директивами (*ngFor, *ngIf) і навчимося керувати самим HTML-кодом програмно.
Це було CS50... тобто, наш урок! До зустрічі! 👋