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 или двустороннюю привязку (об этом позже).
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ