3d cartoon hands holding a phone

Unlock full course by purchasing a membership

Lesson 9

Change Detection: Signals vs OnPush vs Default

Why OnPush change detection matters

STANDARD

Change Detection and Signals

One of the great things about signals is that it will reduce a great deal of the need for us to understand precisely how change detection works in Angular.

Maybe you are starting to notice a theme in this module — the older concepts that we are covering require a great deal of explanation to try and understand the mental model and how everything fits together. The newer alternatives are usually much easier to explain and are generally just more intuitive.

Before signals, there was a lot of benefit in understanding and, to an extent, “gaming” or “optimising” your application to better suit the change detection system and improve performance (or to understand why something changed but you aren’t seeing it render on screen).

I think it will still be important to understand how change detection works with signals, but it won’t be as important as it was before. There will also be much less of these strategies for improving change detection performance.

Unfortunately, although we already have signals available in Angular, Signal Based Components are not yet available. This will likely be coming very soon. Our strategy throughout this course will basically be to just use signals and approach change detection as if Signal Based Components are already available. Then, when they become available, it will be very easy to switch over.

We will not be implementing the old style change detection techniques (like using OnPush), but as usual we will still cover the concepts as you will likely run into Angular applications that are not using Signal Based Components and the new change detection.

The rest of this lesson will be dedicated to the old style of change detection, and when Signal Based Components become available I will update this lesson with some information on specifically how change detection works with signals.

However, the high level story of how change detection with signals works will be something like this: if a signal is updated, the signal will handle notifying Angular that a change has occurred.

As you’re about to see — this is a refreshingly simple idea. The “downside” is that we will need to use signals for any changes we want reflected in the template using this paradigm. With the old method, as complicated and ineffecient as it is, it did allow for basically any change to be reflected no matter how it was made.

Personally, I don’t see being forced to use signals as a downside as they are fantastically powerful and rather simple to use.

Change Detection: OnPush vs Default

To get right to the point: Angular needs to keep track of when things in your application change. Let’s say we have a class member in the class for my component:

@Component({
  standalone: true,
  selector: 'app-home',
  template: `
    <p>{{ name }}</p>
    <button (click)="changeName()">Change name</button>
  `,
})
export class HomeComponent {
  name = 'Josh';

  changeName() {
    this.name = 'Kathy';
  }
}

The value for name is initially Josh and we are displaying that in the template. But, we have a button that triggers the changeName method when clicked which will change this value to Kathy. I encourage you to run this example for yourself, because we are going to play with this a bit.

If you click the button, you might be unsurprised to see that the value displayed in the template changes. This is what we would want to happen, but the underlying mechanisms for Angular to achieve this seemingly simple task aren’t so simple.

We could cause a change to the template in a different way — what about a setTimeout that triggers the change after 2 seconds?

@Component({
  standalone: true,
  selector: 'app-home',
  template: ` <p>{{ name }}</p> `,
})
export class HomeComponent implements OnInit {
  name = 'Josh';

  ngOnInit() {
    setTimeout(() => (this.name = 'Kathy'), 2000);
  }
}

NOTE: We are using one of Angular’s lifecycle hooks here to run some code when the component is initialised. There are other Angular lifecycle hooks like OnDestroy and AfterViewInit as well.

Or, maybe we have a setInterval changing the value every second:

@Component({
  standalone: true,
  selector: 'app-home',
  template: ` <p>{{ value }}</p> `,
})
export class HomeComponent implements OnInit {
  value = 1;

  ngOnInit() {
    setInterval(() => this.value++, 1000);
  }
}

If you run these examples, you will see that in every case the value is updated correctly. Angular detects when these changes occur and updates the template.

How does Angular detect changes?

We aren’t going to get into the precise underlying mechanisms that allow Angular to detect and respond to changes. This can become useful for performance optimisation, but it isn’t something we need to get into right now.

Our main goal in this lesson will be to understand the difference between the

STANDARD
Key

Thanks for checking out the preview of this lesson!

You do not have the appropriate membership to view the full lesson. If you would like full access to this module you can view membership options (or log in if you are already have an appropriate membership).