0
0
Angularframework~5 mins

Smart and dumb component pattern in Angular

Choose your learning style9 modes available
Introduction

This pattern helps separate how data is handled from how it looks. It makes your app easier to understand and change.

When you want to keep your UI simple and focused only on showing data.
When you want to manage data and logic in one place and share it with many UI parts.
When you want to test your UI and logic separately without mixing them.
When your app grows and you want to keep code organized and easy to fix.
When you want to reuse UI parts without copying data logic.
Syntax
Angular
/* Smart component (container) */
@Component({
  selector: 'app-smart',
  standalone: true,
  imports: [DumbComponent],
  template: `<app-dumb [items]="items" (select)="onSelect($event)"></app-dumb>`
})
export class SmartComponent {
  items = ['Apple', 'Banana', 'Cherry'];

  onSelect(item: string) {
    console.log('Selected:', item);
  }
}

/* Dumb component (presentational) */
@Component({
  selector: 'app-dumb',
  standalone: true,
  imports: [CommonModule],
  template: `
    <ul>
      <li *ngFor="let item of items" (click)="select.emit(item)" tabindex="0" role="button" aria-label="Select {{item}}">
        {{item}}
      </li>
    </ul>
  `
})
export class DumbComponent {
  @Input() items: string[] = [];
  @Output() select = new EventEmitter<string>();
}

The smart component holds data and logic.

The dumb component only shows data and sends user actions back.

Examples
This dumb component just shows a message passed from outside.
Angular
/* Dumb component only shows data */
@Component({
  selector: 'app-dumb',
  standalone: true,
  template: `<p>{{message}}</p>`,
  inputs: ['message']
})
export class DumbComponent {
  @Input() message = '';
}
The smart component sends a greeting to the dumb component to display.
Angular
/* Smart component passes data and handles events */
@Component({
  selector: 'app-smart',
  standalone: true,
  imports: [DumbComponent],
  template: `<app-dumb [message]="greeting"></app-dumb>`
})
export class SmartComponent {
  greeting = 'Hello from smart component!';
}
Sample Program

The smart component holds a list of fruits and passes it to the dumb component. The dumb component shows the list and lets the user click an item. When clicked, the dumb component tells the smart component which item was selected. The smart component then logs the selection.

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

@Component({
  selector: 'app-dumb',
  standalone: true,
  imports: [CommonModule],
  template: `
    <ul>
      <li *ngFor="let item of items" (click)="select.emit(item)" tabindex="0" role="button" aria-label="Select {{item}}">
        {{item}}
      </li>
    </ul>
  `
})
export class DumbComponent {
  @Input() items: string[] = [];
  @Output() select = new EventEmitter<string>();
}

@Component({
  selector: 'app-smart',
  standalone: true,
  imports: [DumbComponent],
  template: `<app-dumb [items]="items" (select)="onSelect($event)"></app-dumb>`
})
export class SmartComponent {
  items = ['Apple', 'Banana', 'Cherry'];

  onSelect(item: string) {
    console.log('Selected:', item);
  }
}
OutputSuccess
Important Notes

Use @Input() to send data to dumb components.

Use @Output() with EventEmitter to send events back to smart components.

Keep dumb components free of data fetching or complex logic.

Summary

Smart components manage data and logic.

Dumb components focus on displaying data and user interaction.

This pattern makes your app easier to maintain and test.