Angular change detection strategy simply well explained

 

Angular change detection strategy simply well explained

Angular is an open source framework maintained by Google that is used to develop single page application using HTML and TypeScript. Angular is a component based framework where we need to have a root component, by default we have a root component that is app.component.ts that is bootstrapped to main.ts when we create a brand new application using command:
ng new yourprojectname
By default Angular app performs change detection from top to bottom of all components but as the application grows then we need to make more change to detect to those and let Angular know where to apply this strategy so that unnecessary changes may get avoid and application can go smoothly.

Change Detection Strategy

Consider reading till last , Change detection strategy looks for all angular expressions, bindings in current state of angular application and then change it by new state requested in angular components and modules.
As name defines itself change detection strategy is responsible for every change detects in ongoing angular application by any component change , event change ,binding or any other expression find in the application.
By Default, Angular checks for changes in the components so that it can update the application model then reflect the model in the view of angular template.

AIM of Change Detection Strategy

Every component has an associated change detector present in it when the application starts up. When we make changes in data model or we can say every ngDoCheck
the angular checks for changes detect in the component then re-render the data into the view.

what we can avoid using change detection strategy is we can let angular know that there are some unnecessary changes occurred which will not going to change anything in the view so we avoid them by Change Detection Strategy so that angular only make those changes which are really need to be changed.
@Component({
    selector: 'todo-item',
    template: `<span class="todo" 
       (click)="onEmit()">{{todo.firstname}} - {{todo.description}}
       - completed: {{todo.completed}}</span>`
})
export class TodoItem {
    @Input()
    todo:Todo;

    @Output()
    toggle = new EventEmitter<Object>();

    onEmit() {
        this.toggle.emit(this.todo);
    }
}
In the above code we have @Input and @Output decorators and an event when any change occurs in the @Input and @Output decorators using events or background callings into another components
Then having big applications which does not managed well can leads to many problems which can make delays and have bad performances.
We have Two Change Detection strategies in angular 
  • ChangeDetectionStrategy.Default 
  • ChangeDetectionStrategy.onPush

ChangeDetectionStrategy.Default

In order to know what angular does in ChangeDetectionStrategy.Default stretegy, it looks for new changes in application and then compare it with old one so that it can make decision to update view accordingly.

 The main part of ChangeDetectionStrategy.Default is that it always changes the view with old one every time any changes made to component that is called Dirty checking in Angular.

This can lead to a big problem when we have big application and have many components so it can be congested for angular to know which needs to be changed on view but ChangeDetectionStrategy.Default does not look for specific changes which need to be updated but changes everything around the application.

It performs every change like events, bindings, lists and promises. We must enable this option only when we have small scale application so that angular can manage the change detections on real time and will not be able to make delays. 
import { Component, Input, ChangeDetectionStrategy } from '@angular/core';

@Component({
  selector: 'user-two',
  changeDetection: ChangeDetectionStrategy.Default,
  template: `
    <div>
      <h4>{{ user.name }}</h4>
      <h5>{{ user.age }} years old</h5>
      {{ user.location }} <br />
      {{ user.email }}

      <button (click)="update()">Internal update</button>
      <p>* should update</p>
    </div>
  `
})
export class UserTwoComponent {
  @Input()
  user;

  update() {
    this.user.name = 'Kevin Durant';
  }
}

ChangeDetectionStrategy.onPush

OnPush Strategy can let angular know in component that where to make changes specifically it does not let application go like ChangeDetectionStrategy.Default but only make change when required. for example:
when you want to let change strategy know that you need a change detection in angular app , if automatically trigger the changes in view and make detection. Angular then only checks the changes made in application with any one these 
  • The Input reference changes;
  • An event originated from the component or one of its children;
  • Run change detection explicitly (componentRef.markForCheck());
  • Use the async pipe in the view.
import { Component, Input, ChangeDetectionStrategy } from '@angular/core';

@Component({
  selector: 'user-one',
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `
    <div>
      <h4>{{ user.name }}</h4>
      <h5>{{ user.age }} years old</h5>
      {{ user.location }} <br />
      {{ user.email }}

      <button (click)="update()">Internal update</button>
      <p>* should not update</p>
    </div>
  `
})
export class UserOneComponent {
  @Input()
  user;

  update() {
    this.user.name = 'Lebron James';
  }
}

ChangeDetectorRef Class

Whenever the view is added or removed from the tree we use this method to check change detection for any changes that are to be checked.
We have total 5 methods to check this changes:
abstract class ChangeDetectorRef {
  abstract markForCheck(): void
  abstract detach(): void
  abstract detectChanges(): void
  abstract checkNoChanges(): void
  abstract reattach(): void
}
  • markForCheck() - when ChangeDetectionStrategy of the component is OnPush then you have to manually tell Angular to check and update the view (markForCheck);
  • detach() - With detach() we can be able to avoid detecting any change in a component's child so that no view and data model will be updated.
  • detectChanges()- When we want to detect changes manually we use detectChanges() by injecting  ChangeDetectorRef into component.
  • checkNoChanges() - This is tpo verify that running change detection does not introduce any other changes in component and its tree.
  • reattach() - This is used to reattach the detached view to change detection tree then view and data model attached to tree by default.

Summary 

In this section, we have learned how we can take advantages of Change detection strategies so that the angular application run faster and have better performance.

No comments:

Powered by Blogger.