Как работает привязка данных (data binding) в Angular?

Привязка данных (data binding) в Angular — это механизм синхронизации данных между компонентом и шаблоном. Angular предоставляет несколько видов привязки, каждый из которых подходит для разных сценариев взаимодействия между логикой и представлением. Привязка позволяет динамически отображать данные, реагировать на события и связывать формы с моделью.

1. Типы привязки данных в Angular

Angular поддерживает четыре основных типа привязки данных:

1.1. Интерполяция (Interpolation)

Синтаксис: {{ выражение }}
Позволяет вставлять значения переменных из компонента в HTML.

Пример:

export class AppComponent {
title = 'Привет, Angular!';
}
<h1>{{ title }}</h1>
  • Работает только на чтение;

  • Может включать выражения: {{ title.toUpperCase() }}.

1.2. Односторонняя привязка к свойствам (Property Binding)

Синтаксис: [property]="expression"
Позволяет привязывать значение свойства DOM-элемента к значению из компонента.

Пример:

<input \[value\]="username">
username = 'admin';

Альтернативный синтаксис через bind-:
bind-value="username"

Используется для привязки любых свойств: [disabled], [src], [ngClass], [style].

1.3. Привязка к событиям (Event Binding)

Синтаксис: (event)="handler"
Позволяет реагировать на события DOM и вызывать методы компонента.

Пример:

<button (click)="onClick()">Нажми меня</button>
onClick() {
console.log('Кнопка нажата');
}

Альтернативный синтаксис через on-:
on-click="onClick()"

Можно передавать $event:

<input (input)="onInput($event)">

1.4. Двусторонняя привязка (Two-Way Binding)

Синтаксис: [(ngModel)]="property"
Обеспечивает одновременную синхронизацию между моделью и представлением. Когда пользователь вводит значение, оно автоматически обновляет свойство компонента и наоборот.

Пример:

<input \[(ngModel)\]="username">
<p>Вы ввели: {{ username }}</p>
username = '';

Для работы с ngModel необходимо подключить FormsModule в модуле:

import { FormsModule } from '@angular/forms';
@NgModule({
imports: \[FormsModule\]
})

За кулисами [(ngModel)]="value" — это синтаксический сахар для:

<input \[ngModel\]="value" (ngModelChange)="value = $event">

2. Особенности выражений в шаблоне

  • Разрешены только безопасные выражения: нельзя использовать присваивания, объявления переменных, вызовы глобальных функций (например, window.alert).

  • Angular шаблонный синтаксис ограничен: нельзя вызывать небезопасные методы или обращаться к глобальному состоянию.

  • Шаблонные выражения вызываются при каждом обнаружении изменений (Change Detection).

3. Атрибуты vs Свойства

Важно различать:

  • Атрибут — HTML-атрибут (например, value="123");

  • Свойство — свойство DOM-объекта (input.value = 123).

Пример:

<!-- Установит атрибут, но не значение поля -->
<input attr.value="123">
<!-- Установит значение в DOM -->
<input \[value\]="123">

В Angular привязка через [] работает с DOM-свойствами, а не с атрибутами.

4. Привязка к стилям и классам

4.1. Привязка к классам

<div \[class.active\]="isActive"></div>
<div \[ngClass\]="{ 'active': isActive, 'disabled': isDisabled }"></div>

4.2. Привязка к стилям

<div \[style.color\]="color"></div>
<div \[ngStyle\]="{ 'font-size': fontSize + 'px' }"></div>

5. Безопасная навигация (?.) и пайпы в шаблоне

Для предотвращения ошибок undefined:

<p>{{ user?.profile?.name }}</p>

Использование пайпов:

<p>{{ birthday | date:'longDate' }}</p>

6. Использование шаблонных переменных

Позволяет ссылаться на элементы DOM или компоненты:

<input #myInput type="text">
<button (click)="logValue(myInput.value)">Log</button>

7. Вложенные компоненты и привязка

Передача данных:

<app-user-card \[user\]="currentUser" (selected)="onUserSelect($event)"></app-user-card>

В дочернем компоненте:

@Input() user: User;
@Output() selected = new EventEmitter<User>();

8. Привязка данных в структурных директивах

*ngIf

<p \*ngIf="isVisible">Показать текст</p>

*ngFor

<li \*ngFor="let item of items; let i = index">{{ i }}: {{ item }}</li>

9. Привязка в реактивных формах

Для реактивных форм используется FormControl и formControl директива:

myControl = new FormControl('');
<form \[formGroup\]="form">
<input formControlName="email">
</form>

10. Механизм Change Detection

Angular отслеживает изменения в модели и автоматически обновляет представление. Это делается при каждом событии (например, click, input, таймеры), используя Zone.js. Когда происходит событие:

  • Angular запускает цикл обнаружения изменений;

  • Все шаблоны проверяются на предмет изменений данных;

  • Все привязки пересчитываются;

  • UI синхронизируется с моделью.

Можно оптимизировать поведение через OnPush стратегию обнаружения изменений:

@Component({
changeDetection: ChangeDetectionStrategy.OnPush
})

11. Привязка к SVG и другим элементам

Angular может привязываться к свойствам SVG и нестандартным элементам:

<svg:rect \[attr.width\]="width" \[attr.height\]="height" \[attr.fill\]="color"></svg:rect>

12. Сценарии комбинированной привязки

<input \[value\]="name" (input)="name = $event.target.value">

Это пример ручной реализации двусторонней привязки без ngModel.

13. Ограничения выражений в привязке

В шаблонах запрещено:

  • Операторы присваивания (=);

  • Декларации переменных (let, const);

  • Вызовы new, window, document;

  • Побочные эффекты.

Цель — избежать XSS, повысить производительность и чистоту шаблонов.