I am using ControlValueAccessor to pass data between a child component and a parent which works as expected but when I initialize the component I get always the error
ERROR TypeError: this.onChange is not a function
After that the code works as expected and the values are past from the Child componenet to parent correctly. The section of my code that threows the error is this.onChange(formData.selectField) after I subscribe to the change event. Sio not sure what causes this error and how to get rid of it. I have a feeling that the onChange function is not registered when i try to call it or something like that extend
import {
Component, forwardRef, Input, OnInit, AfterViewInit} from '@angular/core';
import { AbstractControl, ControlValueAccessor, FormControl, FormGroup, NG_VALIDATORS,
NG_VALUE_ACCESSOR, Validators,} from '@angular/forms';
import { Button } from '../models/button.model';
@Component({
selector: 'app-button-toggle',
templateUrl: './button-toggle.component.html',
styleUrls: ['./button-toggle.component.scss'],
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => ButtonToggleComponent),
multi: true,
},
{
provide: NG_VALIDATORS,
useExisting: forwardRef(() => ButtonToggleComponent),
multi: true,
},
],
})
export class ButtonToggleComponent
implements ControlValueAccessor, OnInit, AfterViewInit
{
@Input() guid: string;
@Input() isRequired = false;
@Input() multiSelect = true;
private _disabled = false;
value;
selectField;
form: FormGroup;
onChange: Function;
onTouched: Function;
validateFn: Function;
@Input() trackOptions: Button[];
constructor() {}
ngAfterViewInit() {
console.log('After View Init');
this.getInitialChecked();
}
registerOnChange(fn: (value: any) => void) {
this.onChange = fn;
}
ngOnInit() {
this.selectField = new FormControl(this.value, []);
this.form = new FormGroup({
selectField: this.selectField,
});
if (this.isRequired) {
this.form.get('selectField').setValidators(Validators.required);
this.form.get('selectField').updateValueAndValidity();
this.form.updateValueAndValidity();
}
this.form.valueChanges.subscribe((formData) => {
this.onChange(formData.selectField);
this.value = formData.selectField;
});
}
writeValue(value) {
console.log(value);
this.value = value;
this.form.get('selectField').setValue(this.value);
}
validate(c: FormControl) {
//return this.validateFn(c);
}
registerOnTouched(fn: () => void) {
this.onTouched = fn;
}
onValChange(e: number, b: boolean) {
if (b === true) {
this.setCheckedButton(e);
} else {
this.setUncheckedButton(e);
}
}
CodePudding user response:
registerOnChange
method is called after writeValue
. In write value you're updating your form.
While it's okay to set value for FormControl
within writeValue
method but it's useless to listen to valueChanges
at that point because value comes from consumer and we don't need to notify about it back.
So, try not to fire valueChanges
event within writeValue
by using emitEvent
option:
this.form.get('selectField').setValue(this.value, { emitEvent: false });
^^^^^^^^^^^^^^^^^^^^^