0
0
Angularframework~5 mins

Container and presentational components in Angular

Choose your learning style9 modes available
Introduction

Container and presentational components help organize your app by separating logic from display. This makes your code easier to understand and maintain.

When you want to keep UI simple and focused on showing data.
When you want to reuse UI parts without repeating logic.
When you want to separate data fetching and state management from how things look.
When working in a team where designers and developers work on different parts.
When you want to test UI and logic separately.
Syntax
Angular
/* Presentational component */
import { Component, Input } from '@angular/core';

@Component({
  selector: 'app-user-card',
  standalone: true,
  template: `
    <div>
      <h2>{{ user.name }}</h2>
      <p>{{ user.email }}</p>
    </div>
  `
})
export class UserCardComponent {
  @Input() user!: { name: string; email: string };
}

/* Container component */
import { Component } from '@angular/core';
import { UserCardComponent } from './user-card.component';

@Component({
  selector: 'app-user-container',
  standalone: true,
  imports: [UserCardComponent],
  template: `
    <app-user-card [user]="user"></app-user-card>
  `
})
export class UserContainerComponent {
  user = { name: 'Alice', email: 'alice@example.com' };
}

Presentational components focus on how things look and receive data via @Input().

Container components handle data and logic, then pass data down to presentational components.

Examples
This presentational component emits an event when clicked, letting the container handle what happens next.
Angular
import { Component, Output, EventEmitter } from '@angular/core';

/* Presentational component with event output */
@Component({
  selector: 'app-button',
  standalone: true,
  template: `<button (click)="clicked.emit()">Click me</button>`
})
export class ButtonComponent {
  @Output() clicked = new EventEmitter<void>();
}
The container listens to the event and runs logic, keeping the button simple.
Angular
import { Component } from '@angular/core';
import { ButtonComponent } from './button.component';

/* Container listens to presentational event */
@Component({
  selector: 'app-button-container',
  standalone: true,
  imports: [ButtonComponent],
  template: `<app-button (clicked)="onClick()"></app-button>`
})
export class ButtonContainerComponent {
  onClick() {
    alert('Button clicked!');
  }
}
Sample Program

This example shows a presentational component MessageComponent that only displays a message and a clear button. The container MessageContainerComponent manages the message state and passes it down. It also handles showing and clearing the message.

Accessibility is included with role="alert" and aria-live="polite" so screen readers announce message changes.

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

@Component({
  selector: 'app-message',
  standalone: true,
  template: `
    <div role="alert" aria-live="polite">
      <p>{{ message }}</p>
      <button (click)="clear.emit()" aria-label="Clear message">Clear</button>
    </div>
  `
})
export class MessageComponent {
  @Input() message = '';
  @Output() clear = new EventEmitter<void>();
}

@Component({
  selector: 'app-message-container',
  standalone: true,
  imports: [MessageComponent],
  template: `
    <app-message [message]="currentMessage" (clear)="clearMessage()"></app-message>
    <button (click)="showMessage()">Show Message</button>
  `
})
export class MessageContainerComponent {
  currentMessage = '';

  showMessage() {
    this.currentMessage = 'Hello from container!';
  }

  clearMessage() {
    this.currentMessage = '';
  }
}
OutputSuccess
Important Notes

Use @Input() to pass data from container to presentational components.

Use @Output() with EventEmitter to send events from presentational to container.

Keep presentational components simple and reusable by avoiding data fetching or complex logic inside them.

Summary

Container components handle data and logic.

Presentational components focus on displaying data and UI.

This separation makes your app easier to maintain and test.