Property Binding and Event Binding in Angular

Angular Tutorial: Beginner to Advanced · 3. Components and templates · 3 min read · Updated

Interpolation puts values into text. Two other bindings connect your class and your template in both directions: property binding sends values to elements, and event binding reports what the user did.

What you will learn

  • How to set element properties with [property]
  • How to bind classes and attributes
  • How to react to clicks and typing with (event)

Property binding

Square brackets around a property name mean "set this property from an expression in my class". A familiar example is an image address:

<img [src]="imageUrl" [alt]="imageAlt" width="120" />

The value inside the quotes is an expression, not text. Without the brackets, src="imageUrl" would look for a file literally named imageUrl.

You can bind many properties. Binding disabled is useful for forms and buttons:

<button [disabled]="isSaving">Save</button>

Class and attribute bindings

To switch a CSS class on or off, use [class.name]. For ARIA and other attributes that are not properties, use [attr.name]:

<button [class.liked]="liked" [attr.aria-pressed]="liked">Like</button>

You can also bind a single style, such as [style.color]="textColor".

Event binding

Parentheses around an event name mean "run this code when the event happens". The most common event is click:

<button (click)="toggle()">Like</button>

For events with data, such as typing, Angular provides the event object as $event. You can pass it to a method:

<input (input)="onType($event)" />

Put it together

This component uses all three kinds of binding:

// src/app/like-button/like-button.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-like-button',
  template: `
    <button type="button" [class.liked]="liked" [attr.aria-pressed]="liked" (click)="toggle()">
      {{ liked ? 'Liked' : 'Like' }}
    </button>

    <img [src]="imageUrl" [alt]="imageAlt" width="64" />

    <p>
      <input [value]="draft" (input)="onType($event)" placeholder="Type something" />
    </p>
    <p>You typed: {{ draft }}</p>
  `,
  styles: `
    .liked { background: #16a34a; color: white; }
  `,
})
export class LikeButton {
  protected liked = false;
  protected draft = '';
  protected readonly imageUrl = '/favicon.ico';
  protected readonly imageAlt = 'Site icon';

  protected toggle(): void {
    this.liked = !this.liked;
  }

  protected onType(event: Event): void {
    this.draft = (event.target as HTMLInputElement).value;
  }
}
// src/app/app.ts
import { Component } from '@angular/core';
import { LikeButton } from './like-button/like-button';

@Component({
  imports: [LikeButton],
  selector: 'app-root',
  templateUrl: './app.html',
  styleUrl: './app.css',
})
export class App {}
<!-- src/app/app.html -->
<main>
  <h1>Bindings</h1>
  <app-like-button />
</main>

Click the button and the label and colour change. Type in the box and the text below follows. Here is what happens: the click calls toggle(), which changes liked, and Angular redraws the parts of the template that use it.

Which binding should I use?

  • Data into text: {{ value }}
  • Data into an element property: [property]="value"
  • A user action out to your code: (event)="method()"

Remember the direction. Square brackets go from the class to the template, parentheses go from the template to the class.

Common mistakes

  • Brackets missing: disabled="isSaving" always disables the button, because any text counts as true. Use [disabled]="isSaving".
  • Quotes inside quotes: inside a double-quoted binding use single quotes, such as [class]="'big'".
  • Calling the handler without parentheses: write (click)="toggle()", not (click)="toggle".

Try it yourself

  1. Add a button that clears the text box by setting draft to an empty string.
  2. Bind [style.color] to red when the text is longer than 10 characters.
  3. Disable the Like button once it has been liked, and add a second button that undoes it.

Quick check

  1. Which syntax sends a value from the class to an element property?
  2. What is $event?
  3. Why does disabled="isSaving" not work as expected?

Next, continue with Angular Two-Way Binding: ngModel, ngModelChange and Input Events.

Frequently asked questions

What is the difference between [value] and (input) on an input?

[value] writes a value from your class into the input. (input) tells your code each time the user types. Together they keep the box and the class in sync, and Angular's forms tools do this for you.

Can one element have several event bindings?

Yes. You can bind click, focus, keydown and others on the same element, each with its own handler.