1. Введение
Каждый компонент Angular обычно состоит как минимум из двух файлов (или одного, если всё пишется прямо в декораторе @Component):
- .ts файл (TypeScript): Здесь находится класс компонента, где вы определяете всю логику, данные (переменные) и методы. Это "мозг" вашего компонента. Например, app.component.ts.
- .html файл: Это и есть шаблон. Здесь вы описываете, как будет выглядеть компонент, используя обычный HTML и специальные возможности Angular для отображения динамических данных. Например, app.component.html.
Вспомните наш первый проект my-first-angular-app с прошлой лекции. У него уже есть app.component.ts и app.component.html. Откройте их!
// src/app/app.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-root', // Как этот компонент будет использоваться в HTML
standalone: true, // Мы же теперь "самостоятельные"!
templateUrl: './app.component.html', // Где лежит наш шаблон
styleUrl: './app.component.css' // Где лежат наши стили
})
export class AppComponent {
title = 'Привет, Angular!'; // Вот наша первая переменная
}
<!-- src/app/app.component.html -->
<div>
<h1>Welcome to {{ title }}!</h1>
</div>
Как вы думаете, что отобразится на странице, когда вы запустите ng serve? Правильно, Welcome to Привет, Angular!. Эти двойные фигурные скобки {{ title }} – это и есть та самая магия, о которой мы будем говорить.
2. Интерполяция: {{ curly braces }}
Здесь {{ title }} — это "интерполяция": Angular заменяет этот кусочек на значение свойства title из класса компонента.
Что это такое?
Интерполяция — это способ вставить значение переменной, свойства или даже результат выражения прямо в HTML. Записывается в двойных фигурных скобках: {{ ... }}.
Почему это важно?
Интерполяция — самый простой способ "связать" данные компонента и шаблон. Если вы не умеете интерполировать, то Angular будет для вас просто "HTML с TypeScript рядом".
Как это работает?
- Внутри {{ ... }} вы пишете имя переменной, свойства или выражение.
- Angular вычисляет это выражение и подставляет результат в HTML.
- Если значение меняется — Angular автоматически обновляет DOM (вот она, реактивность!).
Пример 1: Выводим строку
export class AppComponent {
title = 'Мой первый Angular-проект';
}
<h1>{{ title }}</h1>
Результат:
На странице появится Мой первый Angular-проект.
Пример 2: Интерполяция чисел
export class AppComponent {
year = 2025;
}
<p>Текущий год: {{ year }}</p>
Результат: Текущий год: 2025
Пример 3: Интерполяция выражения
export class AppComponent {
a = 5;
b = 7;
}
<p>Сумма: {{ a + b }}</p>
Результат: Сумма: 12
3. Интерполяция: что можно, а что нельзя?
Что можно вставлять в {{ ... }}?
- Свойства и переменные класса компонента
- Результат вызова метода компонента
- Простые выражения (арифметика, логика, тернарный оператор)
- Встроенные объекты и методы JavaScript (например, toUpperCase())
Что нельзя?
- Присваивания (=), объявления переменных (let, var, const)
- Операторы, изменяющие состояние (++, --, a = b)
- Доступ к глобальным переменным вне компонента (например, window, document — только если явно разрешено)
- Сложные конструкции типа циклов и условий (для этого есть директивы, о них позже)
Пример:
<!-- Можно -->
<p>{{ userName.toUpperCase() }}</p>
<p>{{ 10 * 2 + 5 }}</p>
<p>{{ isLoggedIn ? 'Вход выполнен' : 'Гость' }}</p>
<!-- Нельзя -->
<!-- <p>{{ let x = 5 }}</p> // Ошибка -->
<!-- <p>{{ userName = 'Петя' }}</p> // Ошибка -->
Почему нельзя присваивать?
Angular-шаблон — это не полноценный JavaScript-код. Он только "вычисляет" и "отображает", но не "изменяет" данные. Все изменения состояния делаются только в TypeScript-коде компонента.
4. Вызов методов в шаблоне
Иногда хочется не только получить значение свойства, но и вызвать функцию, которая что-то вычисляет.
export class AppComponent {
name = 'Алиса';
getGreeting(): string {
return `Привет, ${this.name}!`;
}
}
<h2>{{ getGreeting() }}</h2>
Результат: Привет, Алиса!
Внимание:
Методы в шаблоне вызываются КАЖДЫЙ РАЗ, когда Angular обновляет шаблон. Не делайте в них тяжелых вычислений или запросов — иначе получите "эффект микроволновки без дверцы" (всё греется, но не там, где надо).
5. Виды интерполяции
Интерполяция и свойства объекта
Если у вас есть объект:
export class AppComponent {
user = {
name: 'Боб',
age: 28
};
}
<p>Имя: {{ user.name }}</p>
<p>Возраст: {{ user.age }}</p>
Интерполяция и массивы
Массив — это тоже объект, и можно обращаться к элементам по индексу:
export class AppComponent {
fruits = ['Яблоко', 'Груша', 'Банан'];
}
<p>Первый фрукт: {{ fruits[0] }}</p>
<p>Всего фруктов: {{ fruits.length }}</p>
Интерполяция и выражения: немного магии
Внутри {{ ... }} можно использовать любые выражения, которые возвращают значение:
- Арифметические (+, -, *, /)
- Логические (&&, ||, !)
- Тернарный оператор (условие ? значение1 : значение2)
- Вызовы методов
Пример:
export class AppComponent {
price = 100;
discount = 0.2;
}
<p>Цена со скидкой: {{ price * (1 - discount) }}</p>
Результат: Цена со скидкой: 80
Интерполяция в атрибутах: подвох
Интерполяция работает не только в тексте, но и внутри некоторых HTML-атрибутов. Например:
<img src="{{ avatarUrl }}">
Но! Для большинства атрибутов Angular рекомендует использовать property binding ([src]="avatarUrl"), о котором мы поговорим на следующей лекции. Интерполяция в атрибутах — это "старый стиль", работает не всегда идеально (например, с boolean-атрибутами).
Интерполяция и экранирование HTML
Интерполяция всегда экранирует HTML — то есть если вы вставите строку с тегами, они не превратятся в элементы, а будут показаны как текст.
export class AppComponent {
unsafeHtml = '<b>Жирный текст</b>';
}
<p>{{ unsafeHtml }}</p>
Результат: <b>Жирный текст</b> (именно текст, а не жирный!)
Зачем это?
Это защищает от XSS-атак (внедрение вредоносного кода). Если вам нужно вставить HTML — используйте innerHTML (но с осторожностью!).
6. Практика: делаем динамическую шапку профиля
Давайте добавим в наше учебное приложение простой профиль пользователя с динамической шапкой.
app.component.ts:
export class AppComponent {
userName = 'Василиса';
userAge = 23;
isPremium = true;
getStatus(): string {
return this.isPremium ? 'Премиум-пользователь' : 'Обычный пользователь';
}
}
app.component.html:
<header>
<h1>Профиль: {{ userName }}</h1>
<p>Возраст: {{ userAge }}</p>
<p>Статус: {{ getStatus() }}</p>
<p>
{{ isPremium ? 'Спасибо за поддержку!' : 'Улучшите аккаунт для новых возможностей.' }}
</p>
</header>
Что получится:
- Имя и возраст выводятся через интерполяцию
- Статус вычисляется функцией
- Сообщение зависит от значения isPremium
7. Типичные ошибки при работе с интерполяцией
В этом разделе — самые частые ошибки, которые совершают новички:
Ошибка №1: Попытка изменить данные в шаблоне
Внутри {{ ... }} нельзя делать присваивания или вызывать методы, которые меняют состояние. Например:
{{ counter++ }} — ошибка!
Интерполяция только для "чтения", не для "изменения".
Ошибка №2: Обращение к несуществующему свойству
Если вы опечатались или такого свойства нет в компоненте, Angular покажет ошибку в консоли:
Cannot read property 'foo' of undefined
Проверьте, что свойство объявлено и правильно написано.
Ошибка №3: Вызовы "тяжёлых" методов
Если в интерполяции вы вызываете функцию, которая долго работает или делает запрос — она будет вызываться очень часто (при каждом "change detection").
Лучше вычислять такие значения заранее и хранить в переменной.
Ошибка №4: Интерполяция в неподдерживаемых местах
Интерполяция не работает внутри некоторых HTML-атрибутов (например, disabled, checked). Для этого есть property binding ([disabled], [checked]).
Ошибка №5: Использование глобальных переменных
В шаблоне доступны только переменные и методы компонента, а не глобальные переменные JavaScript.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ