Search code examples
angularangular2-changedetection

Why properties value does not change in template onPush strategy?


Component.ts

@Component({
  selector: 'app-sample',
  templateUrl: './sample.component.html',
  styleUrls: ['./sample.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class SampleComponent extends SortableComponent implements OnInit {
  public countNumbers: number = 0;
  public sampleItems;

  constructor(private sampleService: SampleService,) {
    super();
  }

  ngOnInit() {
    this.refreshList();
  }

  private refreshList() {
    this.numberOfAssetsLeftToLoad = this.numberOfAssetsLeftToLoad + 1;

this.sampleService
      .getSample()
      .then(
        (response: any) => {
          this.numberOfAssetsLeftToLoad = this.numberOfAssetsLeftToLoad - 1;
          this.sampleItems = response;
        },
        (reason: Error) => {
          this.numberOfAssetsLeftToLoad = this.numberOfAssetsLeftToLoad - 1;
          console.log(reason);
        },
      );
  }
}

Template

<div class="col-sm pt-4" *ngIf="numberOfAssetsLeftToLoad !== 0">
      <loader loadingText="Loading Sample..." cssClass="w-50"></loader>
    </div>
    <div class="col-sm pt-4" *ngIf="numberOfAssetsLeftToLoad === 0">
      <div *ngFor="let item of sampleItems;">{{item}}</div>
    </div>

The problem is that using OnPush strategy values in the template does not change appropriately as in the ts file. For example, numberOfAssetsLeftToLoad stay 1 and loading does not end.


Solution

  • You must manually tell Angular to perform a change detection. Simply inject ChangeDetectorRef and call markForCheck() where you change a property:

    @Component({
      selector: 'app-sample',
      templateUrl: './sample.component.html',
      styleUrls: ['./sample.component.scss'],
      changeDetection: ChangeDetectionStrategy.OnPush,
    })
    export class SampleComponent extends SortableComponent implements OnInit {
      public countNumbers: number = 0;
      public sampleItems;
    
      constructor(private cd: ChangeDetectorRef, private sampleService: SampleService,) {
        super();
      }
    
      ngOnInit() {
        this.refreshList();
      }
    
      private refreshList() {
        this.numberOfAssetsLeftToLoad = this.numberOfAssetsLeftToLoad + 1;
        this.cd.markForCheck();
    
    this.sampleService
          .getSample()
          .then(
            (response: any) => {
              this.numberOfAssetsLeftToLoad = this.numberOfAssetsLeftToLoad - 1;
              this.sampleItems = response;
              this.cd.markForCheck();
            },
            (reason: Error) => {
              this.numberOfAssetsLeftToLoad = this.numberOfAssetsLeftToLoad - 1;
              this.cd.markForCheck();
              console.log(reason);
            },
          );
      }
    }