Search code examples
angularcustom-controlsonchangedynamic-forms

Angular custom control onChange not working properly


I have built a dynamic form with standart and custom control (a simply button scale to push and retrieve the value). I followed the Angular tutorials and others to ensure that I was building the accessors in a right way.

The value of the scale component is always correct and updates correctly. If I click the submit button, the value is ok, but for some reason, the change event doesn't fire.

I created a Stackblitz with the working project and some example data. The purpose is to display the form data on every change, regardless of whether it is a text box, a dropdown menu, or a custom scale component. I also have a Show button to view the values manually.

In the dynamic-form.component.html I have a (change)="onSubmit()" event to display the values.

As you will see, changing textbox or dropdown will show the values, but pressing the scale buttons does not show the values (but it updates correctly, you can see it by pressing the "Show" button).

Any ideas why the change event is not detected? As I understood from reading docs, it is supposed that, in item-scale.component.ts function chooseValue(scaleValue: number), the line this.onChange(this.scaleValue); should trigger the change event, isn't?


Solution

  • We can just listen for value changes on the parent component and trigger the onSubmit, the method using listener is the long way!

    Also by using debounceTime we can reduce the number of times value changes is fired so that the code has better performance!

    You have not defined a change @output for the event to fire that was the issue in your code!

    (change) event only exists on HTML form elements (e.g: input, select, etc.) But we are defining (change) on a angular component, so angular will interpret it as an output event emitter ( @Output), since there is no @Output defined on the child component, we are not getting method triggered

      ...
      ngOnInit() {
        const group: any = {};
    
        this.items.forEach((elem) => {
          group[elem.id] = new FormControl(elem.value || '');
        });
    
        this.form = new FormGroup(group);
    
        this.form.valueChanges.pipe(debounceTime(500)).subscribe(() => {
          this.onSubmit();
        });
      }
      ...
    

    stackblitz demo