Property Binding в Angular — [property], примеры

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

1. Введение

В мире фронтенда часто возникает задача — динамически менять свойства DOM-элементов на основе состояния приложения. Например, сделать кнопку неактивной, если форма невалидна, или показать картинку, путь к которой хранится в переменной компонента.

Конечно, можно попытаться сделать это через интерполяцию, но Angular быстро скажет: "Нет-нет, так не работает!" — и будет прав. Интерполяция ({{ ... }}) подходит только для текста внутри элементов, а вот для свойств элементов нужен другой подход — Property Binding.

Property Binding (связь по свойству) — это способ связать свойство DOM-элемента или Angular-компонента с выражением из класса компонента. Когда значение в компоненте меняется, Angular автоматически обновляет свойство элемента.

Синтаксис Property Binding

Синтаксис простой, как булка хлеба:

<tag [property]="expression"></tag>

Пояснение:

  • [property] — имя свойства DOM-элемента или Angular-компонента, в квадратных скобках.
  • expression — любое выражение на TypeScript, обычно это переменная или функция из класса компонента.

Примеры:

<img [src]="imageUrl">
<button [disabled]="isDisabled">Отправить</button>
<div [hidden]="isHidden">Этот блок можно спрятать</div>

Чем Property Binding отличается от интерполяции?

Интерполяция ({{ ... }}) работает только для текста между тегами. Например:

<h1>{{ userName }}</h1>

Это вставит значение userName между тегами <h1>...</h1>.

Property Binding ([property]="...") изменяет свойство DOM-элемента или Angular-компонента. Например:

<input [value]="userName">

Это присвоит свойству value поля ввода значение userName.

Важный момент:
Иногда кажется, что можно написать <input value="{{ userName }}">, и это сработает. Оно и сработает, но только при инициализации! Если userName поменяется, свойство value не обновится. Поэтому для динамической работы всегда используйте property binding.

2. Практика: Простые примеры Property Binding

Пример 1: Динамическая картинка

export class AppComponent {
  imageUrl = 'https://placekitten.com/200/300';
}
<img [src]="imageUrl" alt="Котик">

Что произойдёт?
В src картинки подставится значение из переменной imageUrl. Если вы поменяете её в коде, картинка на странице сменится автоматически.

Пример 2: Кнопка, которая становится неактивной

export class AppComponent {
  isDisabled = true;
}
<button [disabled]="isDisabled">Нажми меня</button>

Что происходит?
Если isDisabled равен true, кнопка будет неактивна. Если поменять значение на false, кнопка снова станет кликабельной.

Пример 3: Скрытие и показ блока

export class AppComponent {
  isHidden = false;
}
<div [hidden]="isHidden">
  Этот блок можно спрятать или показать!
</div>
<button (click)="isHidden = !isHidden">Показать/Скрыть</button>

Что происходит?
Кнопка переключает значение isHidden, и блок исчезает или появляется.

3. Property Binding и атрибуты: в чём разница?

В HTML у элементов есть атрибуты (attribute) и свойства (property). Иногда они совпадают по названию, иногда — нет. Angular работает именно со свойствами DOM-элементов, а не с их атрибутами.

Различие на примере input

  • <input value="Привет"> — это атрибут value, который задаёт начальное значение поля.
  • input.value — это свойство value, которое отражает текущее значение поля.

Если вы используете:

<input [value]="userName">

Angular присваивает значение userName свойству value. Это актуально и после инициализации.

Если вы пишете:

<input value="{{ userName }}">

Angular подставляет значение только при создании элемента. После этого любые изменения userName не будут видны в поле.

4. Виды Property Binding

Property Binding с булевыми свойствами

Многие свойства элементов — булевые (например, disabled, checked, readonly). Property binding отлично работает с ними.

Пример: Чекбокс

export class AppComponent {
  isChecked = false;
}
<input type="checkbox" [checked]="isChecked">
<button (click)="isChecked = !isChecked">Переключить чекбокс</button>

Что происходит?
Кнопка будет переключать состояние чекбокса.

Property Binding для пользовательских компонентов

Property binding работает не только с обычными HTML-элементами, но и с Angular-компонентами. Это основной способ передавать данные "вниз" — от родителя к дочернему компоненту.

Пример: Передача значения в дочерний компонент


import { Component, Input } from '@angular/core';

@Component({
  selector: 'app-child',
  template: `<p>Получено: {{ value }}</p>`
})
export class ChildComponent {
  @Input() value: string = '';
}

export class AppComponent {
  parentValue = 'Привет из родителя!';
}
<app-child [value]="parentValue"></app-child>

Что происходит?
Значение parentValue из родителя попадёт в свойство value дочернего компонента.

Property Binding и выражения

В property binding можно использовать любые выражения TypeScript (но не слишком сложные — не пишите туда всю бизнес-логику!).


<button [disabled]="userAge < 18 || !isRegistered">
  Зарегистрироваться
</button>

Здесь кнопка будет заблокирована, если возраст пользователя меньше 18 или он не зарегистрирован.

Property Binding vs Атрибут Binding: [attr.xxx]

Иногда нужно изменить именно атрибут элемента, а не его свойство. Например, для нестандартных атрибутов (data-*, aria-*) или когда у элемента нет соответствующего свойства.

Для этого Angular поддерживает attribute binding:


<div [attr.title]="tooltipText"></div>
<div [attr.data-user]="userId"></div>
  • [property] — работает со свойством DOM-элемента.
  • [attr.attribute] — работает с атрибутом.

В большинстве случаев используйте property binding!
Attribute binding нужен только для специфических случаев.

Property Binding и стили/классы

Хотите динамически управлять стилями или классами? Для этого есть специальные директивы:

  • [style.property]="expression" — динамически меняет CSS-свойство.
  • [class.className]="condition" — добавляет/убирает класс.

Примеры:


<div [style.backgroundColor]="isActive ? 'green' : 'gray'">...</div>
<div [class.selected]="isSelected">...</div>

Об этих возможностях подробнее будем говорить в следующих лекциях, но знать о них уже сейчас — полезно!

5. Практический пример: Галерея изображений

Давайте попробуем собрать вместе всё, что узнали.


export class AppComponent {
  images = [
    'https://placekitten.com/200/300',
    'https://placekitten.com/201/300',
    'https://placekitten.com/202/300'
  ];
  currentIndex = 0;

  nextImage() {
    this.currentIndex = (this.currentIndex + 1) % this.images.length;
  }
  prevImage() {
    this.currentIndex =
      (this.currentIndex - 1 + this.images.length) % this.images.length;
  }
}

<div>
  <button (click)="prevImage()">Назад</button>
  <img [src]="images[currentIndex]" alt="Котик">
  <button (click)="nextImage()">Вперёд</button>
</div>

Что происходит?
Картинка меняется при нажатии кнопок, потому что свойство src у <img> связано с переменной компонента через property binding. Всё динамично и без магии!

6. Типичные ошибки при использовании Property Binding

Ошибка №1: Использование интерполяции вместо property binding для свойств

Например, <img src="{{ imageUrl }}"> сработает только при инициализации. Если imageUrl поменяется — картинка не обновится. Всегда используйте [src]="imageUrl".

Ошибка №2: Путаница между свойствами и атрибутами

Иногда пытаются сделать [value] для нестандартного атрибута или [attr.src] для стандартного свойства. Помните: [property] — для свойств, [attr.xxx] — для атрибутов.

Ошибка №3: Присваивание строки булевому свойству

Например, [disabled]="'false'" — это строка 'false', а не булево значение! Нужно писать [disabled]="false" (без кавычек).

Ошибка №4: Сложные выражения прямо в шаблоне

Не пишите в binding сложные вычисления или вызовы функций с побочными эффектами. Лучше вычислить значение в компоненте и передать переменную.

Ошибка №5: Изменение данных только в шаблоне

Property binding работает в одну сторону: из компонента в шаблон. Если хотите получать данные из шаблона в компонент — используйте event binding или двустороннюю привязку (об этом позже).

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