-2

Reactive FormControl element triggers ChangeDetection whenever the input value is changed. I have added OnPush strategy but still it runs ChangeDetection,

@Component({
  selector: 'app-server-input',
  templateUrl: './server-input.component.html',
  styleUrls: ['./server-input.component.css'],
  changeDetection: ChangeDetectionStrategy.OnPush
})

The FormControl directive is the one that triggers ChangeDetection. How do i stop running the ChangeDetection when the input changes?

serverName: FormControl = new FormControl();

Here is my code on StackBlitz.

Note: One thing to note here is if you click on the button, the ngDocheck is called so I have used event manager to stop the change detection.

anonymous
  • 1,499
  • 2
  • 18
  • 39
  • It seems like the internal implementation triggers the OnPush change detection. At this point, it'd be better to change how you are trying to implement your solution. – Trevor Kropp Apr 12 '21 at 06:15
  • https://indepth.dev/posts/1131/if-you-think-ngdocheck-means-your-component-is-being-checked-read-this-article – Robin Dijkhof Apr 12 '21 at 10:10
  • Please read the article, @Robin Dijkhof is the right answer: https://indepth.dev/posts/1131/if-you-think-ngdocheck-means-your-component-is-being-checked-read-this-article – luiscla27 Apr 13 '21 at 15:25
  • You have to understand when there is no fomcontrol assigned then there is no change detection. – anonymous Apr 15 '21 at 04:52

4 Answers4

2

ngDoCheck does always run. No matter what strategy you use. See https://indepth.dev/posts/1131/if-you-think-ngdocheck-means-your-component-is-being-checked-read-this-article and Why do we need `ngDoCheck`

I can't see any reason why you'd want to know when, how are why change-detection has run. If you want to do something on change, just use a setter on your input:

_name: string;
get name(): string{
    return this._name;
}
@Input() set name(value: string) {
    this._name = value;
    this.doUpdateSomething();
}
Robin Dijkhof
  • 18,665
  • 11
  • 65
  • 116
  • I have added a button on the parent component and clicked on it, then the ngDocheck ran on the child component but when I have handled the click event outside ngZone then the nDocheck of the child component did not run. This experiment proves that ngDoCheck dont always run by default – anonymous Apr 12 '21 at 14:21
  • You have to understand when there is no form-control assigned then there the ngDocheck is not run in the child component – anonymous Apr 15 '21 at 04:53
1

I've forked and updated your code: https://stackblitz.com/edit/child-component-2bstm4?file=app/app.component.ts

  ngOnInit() {    
    this.zone.runOutsideAngular(() => (
      this.serverName = new FormControl(),
      this.cd.detach()
      )
    );
  }
  • In contrast to TypeScript Developers, Angular Developers also thought about what would happen if we set a fire and turn off the fire alarm. If you look at the ChangeDetectorRef API, you find that they have thought every possibility. "Detach" is one of them: https://angular.io/api/core/ChangeDetectorRef . All of these steps can be initiated manually, which in the best case scenario should work automatically. –  Apr 18 '21 at 14:34
  • I award the bounty to this answer. But this did not work on my app. – anonymous Apr 18 '21 at 15:07
  • StackBlitz works with zones, where `this.cd.detach()` is specified as a parameter. In your real app, you have to place it before creating the form. –  Apr 18 '21 at 15:10
  • here is my stackblitz -> https://stackblitz.com/edit/github-8scuv6-dym6sc?file=projects%2Fserver-state%2Fsrc%2Fapp%2Fapp.component.ts – anonymous Apr 18 '21 at 15:35
  • I tried already with cd.detach, Its not working. – anonymous Apr 18 '21 at 16:42
  • Did you intentionally used `this.cdr.detectChanges();` ? –  Apr 18 '21 at 17:08
  • Yes because that display component has an on-push strategy and when the observable emits I have to call detect changes method – anonymous Apr 18 '21 at 17:16
  • I'm afraid that after everything is running asynchronously, they'll get in each other's way. You have to reorganize the workflow in your app. I always use async-await to be sure of the execution order. –  Apr 18 '21 at 17:20
0

To prevent angular from running the change detection each time the user interacts with the input field you should detach the change detector. You need to inject the ChangeDetectorRef and call its detach method

  constructor(private cd: ChangeDetectorRef) {}
  ngOnInit() {
    this.cd.detach();
  }

The change detection will no longer be automatically run for this component and its children. When you need to trigger a change detection you can call the detectChanges method on the ChangeDetectorRef.

For exemple this will trigger the change detection every 5 seconds.

  ngOnInit() {
    this.cd.detach();
    setInterval(() => this.cd.detectChanges(), 5000);
  }
J.Loscos
  • 2,478
  • 1
  • 10
  • 17
-1

In the link mentioned below, there is an option to disable change detection on form control

disable form control