2

I have built a dynamic form with standard 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?

1 Answer 1

1

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

Sign up to request clarification or add additional context in comments.

5 Comments

Hi @naren-murali, thanks for your fast response. So, the use of (change) in html is not right in this case? I've tested your solution, it is working perfectly (I have change debounce for throttle, because debounce shows data one step ahead of real value), but still don't understand why (change) doesn't work. You talk about a change @output, can you explaint it a little more?
@Eagle sure give me few minutes
@Eagle (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
Interesting, a new knowledge acquired. And could we "emulate" the (change) in any way to make the HTML work as if the scale component were an standart element? Just to know, because the form.valueChanges is a great solution.
@Eagle Yes, we need to add (change)="change.emit($event)" event on all the standard html components of the child component, and in the child component define an output event emitter like @Output() change: EventEmitter<any> = new EventEmitter<any>(); Then your code will work, the reason I did not go for this method is more code for the same functionality!

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.