DEV Community

Soumaya Erradi
Soumaya Erradi

Posted on

Mastering Angular DevTools

If you’ve ever felt like debugging an Angular app was like solving a puzzle in the dark, you’re not alone. I’ve been there too, opening the browser console, adding console.log() statements, trying to guess why a component keeps re-rendering or where a signal is stuck.

That changed when I started using Angular DevTools.

In this article, I’ll walk you through how Angular DevTools works, what you can do with it, and how to use it to debug smarter and optimize faster, with practical examples and diagrams to help you visualize what’s happening under the hood.

Why Angular DevTools?

Angular is powerful, but sometimes that power makes things harder to trace. Between @Input() bindings, signals, services, lifecycle hooks and change detection, it can be difficult to see what's really going on.

Angular DevTools is a browser extension that gives you real-time insight into:

  • Your component tree
  • Input and output values
  • Signals and state changes
  • Change detection cycles
  • Performance profiling

It’s built to work with Angular 9+ (Ivy is required) and gets better with each version of Angular, especially with the recent addition of signals.

Getting started

First, install Angular DevTools from the Chrome Web Store.

Once installed:

  1. Run your app with ng serve
  2. Open Chrome DevTools
  3. Click on the Angular tab

If you don’t see it, make sure your app isn’t in production mode and that you’re using Ivy (enabled by default in Angular 9+).

Feature breakdown

1. Inspect Components

@Component({
  selector: 'app-user-card',
  template: `
    <h2>{{ user.name }}</h2>
    <p>{{ user.email }}</p>
    <button (click)="toggleActive()">
      {{ user.active ? 'Deactivate' : 'Activate' }}
    </button>
  `,
})
export class UserCardComponent {
  @Input() user: { name: string; email: string; active: boolean };
  @Output() statusChange = new EventEmitter<boolean>();

  toggleActive() {
    this.user.active = !this.user.active;
    this.statusChange.emit(this.user.active);
  }
}
Enter fullscreen mode Exit fullscreen mode

DevTools lets you:

  • Inspect the component tree
  • Edit @Input() values live
  • Trigger outputs and debug events

Component tree diagram

component-tree


2. Debug Signals (Angular 18+)

@Component({
  selector: 'app-counter',
  template: `
    <h3>Count: {{ count() }}</h3>
    <button (click)="increment()">+</button>
  `,
})
export class CounterComponent {
  count = signal(0);

  increment() {
    this.count.set(this.count() + 1);
  }

  constructor() {
    effect(() => {
      console.log('Count changed:', this.count());
    });
  }
}
Enter fullscreen mode Exit fullscreen mode

Signal flow diagram

signal-flow


3. Visualize Change Detection

@Component({
  selector: 'app-product-list',
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `<div *ngFor="let product of products">{{ product.name }}</div>`,
})
export class ProductListComponent {
  @Input() products: Product[];
}
Enter fullscreen mode Exit fullscreen mode

If your list re-renders too often, DevTools helps you catch it.

Change Detection timeline

change-detection


4. Use the Profiler

Record a session and analyze which components rendered and how long they took. This helps pinpoint bottlenecks in dashboards, lists, and forms.


5. Explore the Dependency Injection graph (Experimental)

@Injectable({ providedIn: 'root' })
export class AuthService {
  isLoggedIn = signal(false);
}

@Component({
  selector: 'app-navbar',
  template: `<span *ngIf="auth.isLoggedIn()">Welcome!</span>`,
})
export class NavbarComponent {
  constructor(public auth: AuthService) {}
}
Enter fullscreen mode Exit fullscreen mode

DI graph

dependency-injection


Real-world debugging use cases

  • A parent component was mutating an array, DevTools helps realize it by showing stale inputs.
  • The Profiler showed that a sidebar was re-rendering unnecessarily, OnPush fixed it.
  • A signal wasn't updating because it was tied to a destroyed component.

Tips & tricks

  • ng.getComponent($0) lets you inspect a DOM element’s Angular instance

  • Use ng.profiler.timeChangeDetection() for benchmarks

  • Name your signals for easier tracking:

  const count = signal(0, { name: 'counter' });
Enter fullscreen mode Exit fullscreen mode

Known limitations

  • Works only in development mode
  • Ivy is required
  • Some features are experimental

Conclusion

Angular DevTools helps you answer tough questions: Why is this rendering? What changed? Where is this value coming from? It gives you visibility, speed and confidence when working with modern Angular apps.

Install it, explore your app and see how much easier debugging can be.

Install Angular DevTools

Top comments (0)