I have a component, which implements ControlValueAccessor (via an abstract class which I used for other CVAs in my app) but it also uses a form, which has two more controls, one of which uses a CVA (via the same abstract class), too. This is how it is supposed to work: Parent form <-> Filter CVA <-> Input CVA Right now I can use the input CVA with a parent form and it works fine (can set from form value and can change its value), so: Parent form <-> Input CVA However when I use the intermediate layer, the Filter CVA component is only being updated from Input, but not from the parent form: Parent form <- Filter CVA <- Input CVA but not like this Parent form -> Filter CVA -> Input CVA After trying different ideas with the abstract class implementations and failing with all of them, I am now stuck. Why would a control value accessor fail to be patched from the parent form? Here is the setup: export class ParentComponent extends BaseComponent implements OnInit { constructor( private fb: UntypedFormBuilder ){ super(); this.form = this.fb.group({ id: null, label: null, description: null, assignedTo: null, assignedTags: {tags:[45], state: 'or'}, // does not update underlying components! dueDate: [null, Validators.required], isTemplate: false, templateId: null, canComplete: true, notifyOnCompletion: false, isPrivate: false }); } /** patches the form value ok, but will not update underlying components */ public changeForm(): void { this.form.get('assignedTags').patchValue(null); } } Here is the filter component which seems to fail when setting the value from the outside form, but updates its value when the inner form is being updated @Component({ selector: 'tag-filter', templateUrl: './tag-filter.component.html', styleUrls: ['./tag-filter.component.scss'], providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef( ()=> TagFilterComponent ), multi: true }, { provide: NG_VALIDATORS, useExisting: forwardRef( ()=> TagFilterComponent ), multi: true } ], changeDetection: ChangeDetectionStrategy.OnPush }) export class TagFilterComponent extends AbstractInputComponent implements OnInit { @Output() public changed: EventEmitter<TagFilter> = new EventEmitter(); public tags: Array<any> = []; public form: UntypedFormGroup; public STATES = { truthy: 'or', falsy: 'and' } private firstChange = true; constructor( private fb: UntypedFormBuilder, protected cdr: ChangeDetectorRef ) { super(cdr); this.form = this.fb.group({ tags: [[]], state: 'or' }); } public ngOnInit(): void { this.form.valueChanges .subscribe((res: TagFilter) => { // this never gets triggered from outside, only from the inner form if ( res.tags.length < 2 ) { res.state = 'or'; this.form.patchValue({state: 'or'}, {emitEvent: false}); } const v = {tags: res.tags, state: res.state} if ( !this.firstChange || v.tags.length > 0 ) { this.changed.emit(v); } this.firstChange = false; this.value = v; }); if ( this.initialValue ) { this.form.patchValue(JSON.parse(JSON.stringify(this.initialValue)) ); } } } Here is the HTML markup: <div class="tag-filter"> <form [formGroup]="form"> <tag-input formControlName="tags"></tag-input> <custom-toggle [state]="STATES.truthy" [stateFalse]="STATES.falsy" formControlName="state"></custom-toggle> </form> </div> And here is the Input component, which has a slightly different implementation for a CVA and works both ways: @Component({ selector: 'tag-input', templateUrl: './tag-input.component.html', styleUrls: ['./tag-input.component.scss'], providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef( ()=> TagInputComponent ), multi: true }, { provide: NG_VALIDATORS, useExisting: forwardRef( ()=> TagInputComponent ), multi: true } ] }) export class TagInputComponent extends AbstractInputComponent implements ControlValueAccessor, Validator, OnInit, OnChanges { @Input() public formControlName: string; @Output() public changed: EventEmitter<any> = new EventEmitter(); public allTags: Array<LabelValue> = []; constructor( protected cdr: ChangeDetectorRef, private tags: TagService, private controlContainer: ControlContainer ) { super(cdr); } /** somehow I have this implementation here */ public get control() { return this.controlContainer.control.get(this.formControlName); } public ngOnInit(): void { TagService.newTags = []; this.readTags(); this.control.valueChanges .subscribe(() => { /** triggers as expected */ if ( this.control.pristine ) { this.readTags(); } }); } } Any ideas, why the Filter Component is failing to be updated from outside? Continue reading...