Angular Attribute Binding

Attribute binding with square brackets lets a template set an HTML attribute or DOM property dynamically from component data.

Property Binding vs. Attribute Binding

Square brackets, [property]="expression", are most commonly used for property binding, which sets a DOM property (like an <img> element's src property) directly. True attribute binding uses the attr. prefix - [attr.x]="expression" - and is needed for HTML attributes that have no matching DOM property, such as colspan or aria- attributes.

Property binding vs. attribute binding

import { Component } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';

@Component({
  selector: 'app-table-row',
  standalone: true,
  template: `
    <img [src]="photoUrl" [alt]="altText">

    <td [attr.colspan]="columnSpan">Summary</td>

    <div [attr.aria-label]="accessibleLabel">Menu</div>
  `
})
export class TableRowComponent {
  photoUrl = '/images/profile.jpg';
  altText = 'Profile photo';
  columnSpan = 3;
  accessibleLabel = 'Open main menu';
}

bootstrapApplication(TableRowComponent).catch(err => console.error(err));
Note: colspan and aria-* have no corresponding property on the DOM element object, only an HTML attribute, so [colspan] alone will not work as expected - [attr.colspan] is required.

Common Attribute Bindings

BindingUse Case
[attr.colspan]Dynamic column span on a <td>
[attr.aria-label]Accessible label that changes with state
[attr.disabled]Toggle disabled as a true HTML attribute
[attr.data-id]Custom data-* attributes for scripting or CSS
[attr.role]Dynamic ARIA role for accessibility

Binding Class and Style

Angular provides two specialized binding forms for the class and style attributes: [class.name] toggles a single CSS class based on a boolean expression, and [style.property] sets a single inline style value directly.

Class and style bindings

import { Component } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';

@Component({
  selector: 'app-alert',
  standalone: true,
  template: `
    <div
      class="alert"
      [class.alert-error]="isError"
      [class.alert-success]="!isError"
      [style.fontWeight]="isError ? 'bold' : 'normal'">
      {{ message }}
    </div>
  `
})
export class AlertComponent {
  isError = true;
  message = 'Something went wrong.';
}

bootstrapApplication(AlertComponent).catch(err => console.error(err));

Removing an Attribute Entirely

Binding an attribute expression to null or undefined removes the attribute from the element completely, rather than leaving it present with an empty value. This is the correct way to conditionally include boolean attributes like disabled or required.

Conditionally present attribute

import { Component } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';

@Component({
  selector: 'app-submit-button',
  standalone: true,
  template: `
    <button [attr.disabled]="isSubmitting ? true : null">
      {{ isSubmitting ? 'Saving...' : 'Save' }}
    </button>
  `
})
export class SubmitButtonComponent {
  isSubmitting = false;
}

bootstrapApplication(SubmitButtonComponent).catch(err => console.error(err));
  • [property] binds to a DOM property; use it for most dynamic values
  • [attr.name] binds to an HTML attribute directly; use it when no DOM property exists
  • [class.name] toggles one CSS class based on a boolean
  • [style.prop] sets one inline style value
  • Binding attr.* to null or undefined removes the attribute
Note: When unsure whether to use property or attribute binding, default to plain property binding ([src], [value], [disabled]) - it covers the vast majority of cases, and Angular documentation calls out the exceptions like colspan explicitly.