Модуль 10

Two-way Binding та ngModel

Ось готовий урок, створений спеціально для тебе у стилі CS50. Вмикай редактор коду, поїхали!


🎓 УРОК: Two-way Binding та магія [(ngModel)]

Привіт, друзі! 👋 Я радий бачити вас на цій лекції.

Сьогодні ми говоримо про тему, яка перетворює ваші додатки з "німих" статичних сторінок на живі, інтерактивні інтерфейси. Ми розберемо Two-way Binding (двостороннє зв'язування) та директиву ngModel в Angular.


1. 🔥 Вступ: Дзеркало та ефект запізнення

Уявіть, що ви зранку підходите до дзеркала, щоб почистити зуби. Ви відкриваєте рота... а ваше відображення стоїть нерухомо. Ви чекаєте 5 секунд, натискаєте кнопку "Оновити відображення", і тільки тоді дзеркало показує, що ви відкрили рота.

Це було б жахливо, правда?

У веб-розробці часто виникає саме така проблема. У нас є дані (у вашому JavaScript/TypeScript коді) і є відображення (HTML). * Коли ви змінюєте змінну в коді — ви хочете, щоб це миттєво побачив користувач. * Коли користувач щось друкує в полі вводу — ви хочете, щоб ця змінна в коді миттєво оновилася.

Питання до вас: Ви хочете писати десятки рядків коду, щоб вручну відловлювати кожну букву, яку ввів користувач, і переписувати змінну?

Звісно, ні. Саме тут на сцену виходить Two-way Binding. Це механізм, який робить ваш інтерфейс дзеркалом: дані змінюються — картинка оновлюється. Картинка змінюється — дані оновлюються. Миттєво.


2. 🧠 Теоретична база (Що під капотом?)

Давайте заглянемо під капот. В Angular (і багатьох інших фреймворках) є два потоки даних:

  1. Property Binding []: Дані течуть від Коду до HTML (вниз).
    • Аналогія: Проектор. Комп'ютер показує картинку на екрані.
  2. Event Binding (): Дані течуть від HTML до Коду (вгору).
    • Аналогія: Клавіатура. Ви тиснете клавіші, комп'ютер реагує.

Two-way binding — це поєднання обох цих процесів одночасно.

Синтаксис "Банан у коробці" 🍌📦

В Angular для цього використовується спеціальний синтаксис: [()]. Запам'ятайте цю візуальну аналогію: круглі дужки (банан) всередині квадратних дужок (коробка).

<input [(ngModel)]="userName">

Що відбувається "під капотом"?

Коли ви пишете цей короткий код, Angular насправді розгортає його у щось таке:

  1. Він бере значення змінної userName і записує його в value інпута (зв'язування властивості []).
  2. Він слухає подію 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. 🧩 Підсумок

Отже, що ми сьогодні поклали у свою валізу знань:

  1. Двостороннє зв'язування — це синхронізація даних між TS і HTML в реальному часі.
  2. Синтаксис — "Банан у коробці" [(ngModel)].
  3. Використання — Ідеально для полів вводу (input, select, textarea, checkbox).
  4. Умова — Потрібен FormsModule.

Тепер ви вмієте створювати інтерфейси, які "відчувають" користувача миттєво.

🚀 Тизер наступного уроку: А що, як нам треба показати не одне ім'я, а список із 100 студентів? Копіювати 100 разів тег <div>? Ні! На наступному уроці ми познайомимося з Структурними директивами (*ngFor, *ngIf) і навчимося керувати самим HTML-кодом програмно.

Це було CS50... тобто, наш урок! До зустрічі! 👋