Skip to content

Angular Property Binding

Property binding lets you set a DOM element property, or a child component's input, directly from a TypeScript expression. This lesson explains the syntax and where it differs from plain HTML attributes.

What Is Property Binding?

Property binding uses square brackets, [property]="expression", to set a DOM property (not just an HTML attribute) to the result of a TypeScript expression evaluated on the component class.

This distinction matters because many DOM properties don't have a simple string equivalent, disabled is a boolean, src needs a real URL string, and a component's custom @Input() might expect an entire object.

@Component({
  selector: 'app-avatar',
  standalone: true,
  template: `
    <img [src]="user.avatarUrl" [alt]="user.name" />
    <button [disabled]="isLoading">Refresh</button>
  `,
})
export class AvatarComponent {
  user = { avatarUrl: '/img/avatar.png', name: 'Ada' };
  isLoading = false;
}

[disabled]="isLoading" sets the actual boolean disabled property, toggling correctly as isLoading changes.

Property Binding Syntax

[property]="expression"
[attr.name]="expression"
[class.className]="expression"
[style.property]="expression"
  • [property] targets a DOM element property directly (like .value, .disabled, .src).
  • [attr.name] targets an HTML attribute explicitly, useful for attributes with no matching DOM property (like aria-* or colspan).
  • [class.name] toggles a single CSS class based on a boolean expression.
  • [style.property] sets a single inline CSS property directly.

Angular Property Binding Cheatsheet

Common property, attribute, class, and style bindings you'll write often.

Binding Example Notes
DOM property [value]="name" Binds the live property, not the attribute
Boolean property [disabled]="isSaving" Sets a real boolean, not the string "false"
Attribute binding [attr.aria-label]="label" For attributes with no DOM property
Single class [class.active]="isActive" Toggles one class conditionally
Class object [class]="classMap" Sets multiple classes from an object/string
Single style [style.color]="textColor" Sets one inline style property
Component input [title]="pageTitle" Passes data into a child's @Input()/input()

Property Binding vs Attribute Binding

Most HTML attributes have a matching DOM property with the same name and Angular's [property] syntax targets that property by default. Some attributes, however, have no DOM property equivalent (like colspan or custom data-*/aria-* attributes), for those, use the explicit [attr.name] form.

<td [attr.colspan]="totalColumns"></td>
<div [attr.aria-expanded]="isOpen"></div>

Without attr., Angular would look for a colspan or ariaExpanded DOM property, which doesn't exist for colspan and is named differently for ARIA.

Binding to Component Inputs

The same [property] syntax used for native DOM properties is also how you pass data into a child component's @Input() (or input() signal input). Angular resolves whether the target is a DOM property or a component input based on the element/component being bound to.

<app-product-card [title]="product.title" [price]="product.price">
</app-product-card>

When to Use Interpolation Instead

Interpolation ({{ }}) is really just a readable shorthand for property binding when the target is a string, text content or a string attribute value. Anything non-string (booleans, numbers used as numbers, objects) requires square-bracket property binding.

<!-- equivalent for string values -->
<img src="{{ imageUrl }}" />
<img [src]="imageUrl" />

<!-- only property binding works correctly here -->
<button [disabled]="isSaving">Save</button>

Common Mistakes

  • Using interpolation to set boolean properties like disabled="{{ isSaving }}", which always evaluates truthy as a string.
  • Forgetting the attr. prefix for attributes without a matching DOM property, like colspan or custom data-* attributes.
  • Binding a whole object to [class] when only a single conditional class is needed ([class.active] is simpler).
  • Assuming [value] on native form controls behaves like two-way binding; it is one-way unless combined with an event binding or ngModel.

Key Takeaways

  • Property binding ([property]) sets a real DOM property, not just a string attribute.
  • Use [attr.name] for attributes without a corresponding DOM property.
  • [class.name] and [style.property] are convenient shorthands for single conditional classes or styles.
  • The exact same [property] syntax is used to pass data into a child component's inputs.

Pro Tip

When in doubt about interpolation vs property binding, default to property binding ([ ]) for anything other than plain text content, it avoids subtle bugs with booleans and numbers rendered as strings.