UI Development

Change Detection in Angular 2

What is Change Detection?

The basic task of change detection is to take the internal state of a program and make it somehow visible to the user interface. This state can be any kind of objects, arrays, primitives, just any kind of JavaScript data structures.

Why do we need Change Detection?

Generally, the power of modern JavaScript frameworks works something like this: an event changes in the model and forcing a change in the UI. This is change detection, the system that monitors events and acts on them.

What causes Change Detection?

An Angular application is a reactive system, with change detection being the core of it. Angular has to run its change detection in the background at specific points where the model state can change.
Model state can change as a result of three things:-

  • DOM Events – click, submit, keyup, etc

For Example:-

/**Component*/
@component({
	template:`
		<h1>{{firstName}} {{lastName}}</h1>
		<button (click)="changeName()">Change Name</button>
	` 
})

class MyApp{

	firstName:string = 'Nausheen';
	lastName:string = 'Saraf';

	changeName(){
		this.firstName = 'John';
		this.lastName = 'Doe';
	}
}

The component above simply displays two properties and provides a method to change them when the  button in the template is clicked. The moment this particular button is clicked is the moment when application state has changed, because it changes the properties of the component. That’s the moment we want to update the view.

  • AJAX requests
  • Timers – setTimeout(), setInterval()

They are all asynchronous. Which brings us to the conclusion that, basically whenever some asynchronous operation has been performed, our application state might have changed.

Who notifies Angular?

But what is it that tells Angular, that at this particular moment, the view has to be updated? Zones take care of this. Zones are a sort of execution context that allows us to hook into our asynchronous tasks. Zones are able to track the context of asynchronous actions by monkey-patching them (i.e., overwriting them with its own code), which then invokes the desired action but with some additional information attached. This additional information is the context. This way, Angular will know which component the asynchronous action was invoked from.

 

In this approach, we can use the browser APIs natively, and Angular will know what’s going on without forcing us to manually tell it that a change has occured. The drawback is that Zones overwrite asynchronous actions, which is kind of a hacky solution and may affect other (existing) code if we’re not relying only on Angular in the app.

 

But exactly how is Angular notified of the change? Angular uses its own version of the Zone called NgZone, which relays finished asynchronous actions with the onTurnDone event. Angular change detection waits for the event to perform change detection and checks what needs to be updated in the UI. That’s the core behavior.

Change Detection

Every angular app is a tree of components.

Each component has its own change detector. Each change detector is created, based on the data structure of the component that it targets. So, the change detector for app component is different from the change detector for the movie component. This allows us to control, for each component individually, how and when change detection is performed. This is for performance optimization. In this way, it can perform several thousand checks in just a few milliseconds. Since each component has its own change detector, and an Angular application consists of a component tree, the logical result is that we’re having a change detector tree too. This tree can also be viewed as a directed graph where data always flows from top to bottom.

At runtime, angular creates a change detector class for every component in this tree., So. Just like we have a tree of components, we have a tree of change detectors.

The reason why data flows from top to bottom, is because change detection is also always performed from top to bottom for every single component, every single time, starting from the root component. This is awesome, as unidirectional data flow is more predictable than cycles. We always know where the data we use in our views comes from, because it can only result from its component.

Another interesting observation is that change detection gets stable after a single pass. Meaning that, if one of our components causes any additional side effects after the first run during change detection, Angular will throw an error.

 

Smarter Change Detection

There are data structures that give us some guarantees of when something has changed or not – Immutables and Observables. If we happen to use these structures or types, and we tell Angular about it, change detection can be much much faster.

 

Immutables

Angular can skip entire change detection sub-trees when input properties don’t change. A “change” means “new reference” in case of use immutable objects. If we use immutable objects in our Angular app, all we need to do is tell Angular that a component can skip change detection, if its input hasn’t changed.

 

Observables

Observables also give us some certain guarantees of when a change has happened. Unlike immutable objects, they don’t give us new references when a change is made. Instead, they fire events we can subscribe to in order to react to them.

 

Summary:

  • An Angular 2 application is a reactive system.
  • The change detection system propagates bindings from the root to leaves.
  • The change detection graph is a directed tree. As a result, the system is more performant and predictable.
  • By default, the change detection system walks the whole tree. But if you use immutable objects or observables, you can take advantage of them and check parts of the tree only if they “really change”.

About The Author

Leave a Reply

*