0

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);
    }
  }

1 Answer 1

3

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 });
                                                  ^^^^^^^^^^^^^^^^^^^^^
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks that got rid of the error, like i said before even so it worked before i don't like errors hanging around.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.