JavaRush /Курсы /Модуль 4: Node.js, Next.js и Angular /Шаблоны Angular: {{ interpol...

Шаблоны Angular: {{ interpolation }}, выражения

Модуль 4: Node.js, Next.js и Angular
13 уровень , 5 лекция
Открыта

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.

Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ