> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/angular/angular/llms.txt
> Use this file to discover all available pages before exploring further.

# Change Detection

> Deep dive into Angular change detection strategies and performance optimization

## Overview

Angular's change detection system is responsible for synchronizing your application's data model with its view. Understanding how it works is crucial for building performant applications.

## Change Detection Strategies

Angular provides two primary change detection strategies that control when and how components are checked for changes.

### Default (Eager) Strategy

The `Default` strategy (also known as `Eager`) checks the component eagerly during every change detection cycle.

```typescript theme={null}
import { Component, ChangeDetectionStrategy } from '@angular/core';

@Component({
  selector: 'app-eager',
  template: `
    <h2>{{ title }}</h2>
    <p>Checked: {{ getCheckedCount() }}</p>
  `,
  changeDetection: ChangeDetectionStrategy.Default
})
export class EagerComponent {
  title = 'Eager Component';
  private checkedCount = 0;

  getCheckedCount(): number {
    return ++this.checkedCount;
  }
}
```

<Note>
  The `Default` strategy has been renamed to `Eager` in recent versions. Both names refer to the same behavior.
</Note>

### OnPush Strategy

The `OnPush` strategy only checks the component when:

* An input property reference changes
* An event originates from the component or its children
* Change detection is manually triggered
* An observable linked to the template emits a new value

```typescript theme={null}
import { Component, ChangeDetectionStrategy, Input } from '@angular/core';

interface User {
  id: number;
  name: string;
  email: string;
}

@Component({
  selector: 'app-user-card',
  template: `
    <div class="card">
      <h3>{{ user.name }}</h3>
      <p>{{ user.email }}</p>
      <button (click)="onEdit()">Edit</button>
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class UserCardComponent {
  @Input() user!: User;

  onEdit(): void {
    // Event handler triggers change detection
    console.log('Editing user:', this.user.id);
  }
}
```

## Manual Change Detection

### ChangeDetectorRef

Use `ChangeDetectorRef` to manually control change detection in your components.

```typescript theme={null}
import { 
  Component, 
  ChangeDetectionStrategy, 
  ChangeDetectorRef,
  OnInit,
  OnDestroy 
} from '@angular/core';
import { interval, Subscription } from 'rxjs';

@Component({
  selector: 'app-manual-cd',
  template: `
    <div class="status">
      <h3>Real-time Data</h3>
      <p>Counter: {{ counter }}</p>
      <p>Last Updated: {{ lastUpdate | date:'medium' }}</p>
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class ManualChangeDetectionComponent implements OnInit, OnDestroy {
  counter = 0;
  lastUpdate = new Date();
  private subscription?: Subscription;

  constructor(private cdr: ChangeDetectorRef) {}

  ngOnInit(): void {
    // Update data outside Angular's zone
    this.subscription = interval(1000).subscribe(() => {
      this.counter++;
      this.lastUpdate = new Date();
      
      // Manually trigger change detection
      this.cdr.markForCheck();
    });
  }

  ngOnDestroy(): void {
    this.subscription?.unsubscribe();
  }
}
```

### Key Methods

<CodeGroup>
  ```typescript markForCheck() theme={null}
  // Marks the component and its ancestors for checking
  // Use with OnPush strategy
  this.cdr.markForCheck();
  ```

  ```typescript detectChanges() theme={null}
  // Immediately runs change detection for this component and its children
  this.cdr.detectChanges();
  ```

  ```typescript detach() theme={null}
  // Detaches the component from change detection tree
  this.cdr.detach();
  ```

  ```typescript reattach() theme={null}
  // Reattaches the component to change detection tree
  this.cdr.reattach();
  ```
</CodeGroup>

## Performance Optimization

### Immutable Data Patterns

When using `OnPush`, work with immutable data to ensure change detection triggers correctly.

```typescript theme={null}
import { Component, ChangeDetectionStrategy } from '@angular/core';

interface TodoItem {
  id: number;
  title: string;
  completed: boolean;
}

@Component({
  selector: 'app-todo-list',
  template: `
    <div *ngFor="let todo of todos; trackBy: trackByFn">
      <app-todo-item 
        [todo]="todo" 
        (toggle)="onToggle($event)"
      ></app-todo-item>
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class TodoListComponent {
  todos: TodoItem[] = [
    { id: 1, title: 'Learn Angular', completed: false },
    { id: 2, title: 'Build an app', completed: false }
  ];

  onToggle(id: number): void {
    // Create new array reference for OnPush to detect change
    this.todos = this.todos.map(todo => 
      todo.id === id 
        ? { ...todo, completed: !todo.completed }
        : todo
    );
  }

  trackByFn(index: number, item: TodoItem): number {
    return item.id;
  }
}
```

### Avoiding Common Pitfalls

<Warning>
  Avoid calling functions or methods directly in templates with `OnPush` strategy, as they may not be re-evaluated when expected.
</Warning>

```typescript theme={null}
// ❌ Bad: Function calls in template
@Component({
  template: `<p>{{ getFormattedDate() }}</p>`,
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class BadComponent {
  getFormattedDate(): string {
    return new Date().toISOString();
  }
}

// ✅ Good: Use pipes or properties
@Component({
  template: `<p>{{ currentDate | date:'medium' }}</p>`,
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class GoodComponent {
  currentDate = new Date();
}
```

## Change Detection with Signals

When using signals in your templates, Angular automatically tracks dependencies and triggers change detection efficiently.

```typescript theme={null}
import { Component, signal, computed, ChangeDetectionStrategy } from '@angular/core';

@Component({
  selector: 'app-counter',
  template: `
    <div class="counter">
      <p>Count: {{ count() }}</p>
      <p>Double: {{ doubled() }}</p>
      <button (click)="increment()">Increment</button>
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class CounterComponent {
  count = signal(0);
  doubled = computed(() => this.count() * 2);

  increment(): void {
    this.count.update(n => n + 1);
  }
}
```

<Check>
  Signals work seamlessly with `OnPush` change detection, automatically marking components for check when signal values change.
</Check>

## Zone.js Integration

Angular uses Zone.js to automatically detect asynchronous operations and trigger change detection.

```typescript theme={null}
import { Component, NgZone } from '@angular/core';

@Component({
  selector: 'app-zone-aware',
  template: `<p>Data: {{ data }}</p>`
})
export class ZoneAwareComponent {
  data = 'initial';

  constructor(private ngZone: NgZone) {
    // Run code outside Angular's zone for performance
    this.ngZone.runOutsideAngular(() => {
      setInterval(() => {
        // Update data outside zone
        const newData = this.fetchData();
        
        // Run change detection when needed
        this.ngZone.run(() => {
          this.data = newData;
        });
      }, 5000);
    });
  }

  private fetchData(): string {
    return `Updated at ${new Date().toLocaleTimeString()}`;
  }
}
```

## Best Practices

<CardGroup cols={2}>
  <Card title="Use OnPush" icon="gauge-high">
    Set `OnPush` strategy on presentational components to reduce unnecessary checks.
  </Card>

  <Card title="Immutable Data" icon="lock">
    Use immutable data patterns to make change detection reliable and predictable.
  </Card>

  <Card title="TrackBy Functions" icon="fingerprint">
    Always use `trackBy` with `*ngFor` to minimize DOM operations.
  </Card>

  <Card title="Avoid Heavy Computations" icon="bolt">
    Move expensive calculations to pipes or pre-compute them in component logic.
  </Card>
</CardGroup>

## Additional Resources

* [Signals Documentation](/advanced/signals)
* [Zoneless Change Detection](/advanced/zoneless)
* [Angular Performance Guide](https://angular.dev/best-practices/runtime-performance)
