Issue
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>
Solution
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:
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>
Answered By - Max Koretskyi
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.