Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ChangeDetectionStrategy.OnPush breaks the disabled state of a ControlValueAccessor

In my Angular app, I've created a custom form element by implementing the ControlValueAccessor interface.

So in my component I correctly implement all methods of that interface, including setDisabledState:

/**
 * This function is called when the control status changes to or from "disabled".
 * Depending on the value, it will enable or disable the appropriate DOM element.
 *
 * @param isDisabled
 */
setDisabledState(isDisabled: boolean): void {
  this.disabled = isDisabled;
}

Everything works fine.

The problem is when I change the ChangeDetectionStrategy of my component setting it to OnPush.

By doing that, the enable/disable functionality of my component is broken.

like image 556
Francesco Borzi Avatar asked Aug 22 '18 09:08

Francesco Borzi


2 Answers

The problem can be solved by manually triggering the change detection.

We need to inject the ChangeDetectorRef into our component:

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

// ...

constructor(
  private cd: ChangeDetectorRef,
) { }

then use it to manually trigger the change detection whenever the enabled/disabled status changes:

setDisabledState(isDisabled: boolean): void {
  this.disabled = isDisabled;
  this.cd.markForCheck(); // this will manually trigger the change detection
}
like image 178
Francesco Borzi Avatar answered Oct 28 '22 08:10

Francesco Borzi


OnPush can only make sense if we are talking about parent / child components communication. when the child has changeDetection: ChangeDetectionStrategy.OnPush setting and the parent is passing an object as an input to the child.

If you are creating a Reactive Custom Form Control which has its own state. It's good to avoid using onPush. If you want to use, you can manually call the Change detection manually using cdr.markforCheck().

like image 20
Suresh Kumar Ariya Avatar answered Oct 28 '22 07:10

Suresh Kumar Ariya