Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why isn't Angular calling registerOnChange in my implementation of ControlValueAccessor?

I'm trying to implement a custom form control component inside a template-drive form in Angular 4. Because I want it to integrate nicely with the parent form, I am trying to implement it as a ControlValueAccessor. I have followed the guides I could find but Angular is not cooperating. According to the documentation, it should be calling my implementation of registerOnChange(), but it doesn't. Why is that?

/* editor-clause.component.ts */
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { QueryClause } from '../../../../models/query-clause';
import { Input, Component, EventEmitter, Output } from '@angular/core';

@Component({
  moduleId: module.id,
  providers: [{
    provide: NG_VALUE_ACCESSOR,
    useExisting: EditorClauseComponent,
    multi: true,
  }],
  selector: 'editor-clause',
  templateUrl: './editor-clause.component.html',
  styleUrls: ['./editor-clause.component.css']
})
export class EditorClauseComponent implements ControlValueAccessor {
  @Input('clause') clause: QueryClause;
  parentOnChange: any;

  writeValue(_obj: any): void {
    return;
  }

  registerOnChange(fn: any): void {
    // This never gets printed and I don't know why
    console.log('Registering parent change tracking');
    this.parentOnChange = () => {
      console.log('Saw a change. Invoking parent function');
      fn();
    };
  }

  registerOnTouched(_fn: any): void {
    return;
  }

}

The containing parent form looks something like:

<form #queryBuilderForm="ngForm">

    <p>Form instructions here</p>

    <editor-clause *ngFor="let clause of clauses" [clause]="clause"></editor-clause>

    <button (click)="addClause()" id="add-query-clause-button">Add clause</button>
</form>
like image 620
Stewart Avatar asked Dec 22 '17 12:12

Stewart


People also ask

What is ControlValueAccessor in Angular?

Control Value Accessor is an interface that provides us the power to leverage the Angular forms API and create a communication between Angular Form API and the DOM element. It provides us many facilities in angular like we can create custom controls or custom component with the help of control value accessor interface.

What is writeValue in Angular?

The writeValue method is called by the Angular forms module whenever the parent form wants to set a value in the child control.

What is Ng_value_accessor?

NG_VALUE_ACCESSOR provider specifies a class that implements ControlValueAccessor interface and is used by Angular to setup synchronization with formControl . It's usually the class of the component or directive that registers the provider.


1 Answers

As explained in the article Never again be confused when implementing ControlValueAccessor in Angular forms the ControlValueAccessor is an intermediary between native control and Angular's form control:

enter image description here

The Angular form control can be created automatically by applying NgModel directive like this:

<editor-clause ngModel *ngFor="let clause of clauses" [clause]="clause"></editor-clause>

Or manually in the component and then bound to a control using formControl directive:

export class EditorClauseComponent ... {
    myControl = new FormControl();

Template:

<editor-clause formControl="myControl" *ngFor="let clause of clauses" [clause]="clause"></editor-clause>
like image 89
Max Koretskyi Avatar answered Sep 20 '22 08:09

Max Koretskyi