Triggering change detection manually in Angular

AngularAngular2 Changedetection

Angular Problem Overview


I'm writing an Angular component that has a property Mode(): string.

I would like to be able to set this property programmatically not in response to any event.

The problem is that in the absence of a browser event, a template binding {{Mode}} doesn't update.

Is there a way to trigger this change detection manually?

Angular Solutions


Solution 1 - Angular

Try one of these:

  • ApplicationRef.tick() - similar to AngularJS's $rootScope.$digest() -- i.e., check the full component tree
  • NgZone.run(callback) - similar to $rootScope.$apply(callback) -- i.e., evaluate the callback function inside the Angular zone. I think, but I'm not sure, that this ends up checking the full component tree after executing the callback function.
  • ChangeDetectorRef.detectChanges() - similar to $scope.$digest() -- i.e., check only this component and its children

You can inject ApplicationRef, NgZone, or ChangeDetectorRef into your component.

Solution 2 - Angular

I used accepted answer reference and would like to put an example, since Angular 2 documentation is very very hard to read, I hope this is easier:

  1. Import NgZone:

     import { Component, NgZone } from '@angular/core';
    
  2. Add it to your class constructor

     constructor(public zone: NgZone, ...args){}
    
  3. Run code with zone.run:

     this.zone.run(() => this.donations = donations)
    

Solution 3 - Angular

I was able to update it with markForCheck()

Import ChangeDetectorRef

import { ChangeDetectorRef } from '@angular/core';

Inject and instantiate it

constructor(private ref: ChangeDetectorRef) { 
}

Finally mark change detection to take place

this.ref.markForCheck();

Here's an example where markForCheck() works and detectChanges() don't.

https://plnkr.co/edit/RfJwHqEVJcMU9ku9XNE7?p=preview >EDIT: This example doesn't portray the problem anymore :( I believe it might be running a newer Angular version where it's fixed.

(Press STOP/RUN to run it again)

Solution 4 - Angular

In Angular 2+, try the @Input decorator

It allows for some nice property binding between parent and child components.

First create a global variable in the parent to hold the object/property that will be passed to the child.

Next create a global variable in the child to hold the object/property passed from the parent.

Then in the parent html, where the child template is used, add square brackets notation with the name of the child variable, then set it equal to the name of the parent variable. Example:

<child-component-template [childVariable] = parentVariable>
</child-component-template>

Finally, where the child property is defined in the child component, add the Input decorator:

@Input()
public childVariable: any

When your parent variable is updated, it should pass the updates to the child component, which will update its html.

Also, to trigger a function in the child component, take a look at ngOnChanges.

Solution 5 - Angular

ChangeDetectorRef.detectChanges() - similar to $scope.$digest() -- i.e., check only this component and its children

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionjz87View Question on Stackoverflow
Solution 1 - AngularMark RajcokView Answer on Stackoverflow
Solution 2 - AngularsitesView Answer on Stackoverflow
Solution 3 - AngularNuno TomasView Answer on Stackoverflow
Solution 4 - AngularJeremy SwaggerView Answer on Stackoverflow
Solution 5 - AngularChetannView Answer on Stackoverflow