0

I have a problem using a reactive form in an Angular app. I managed to isolate the problem in a Plunkr.

https://plnkr.co/edit/KiTHcaaZZA6kwDI0sfeR?p=preview

What I have is a form with an ArrayForm section where I can add rows with a button. Every one of these rows has many input fields, and a few of them display the result of other fields. For example, in my plunkr I have a MAX and a MIN button, which are numbers, and when both of them have a value, I need to update the value of another field, called TOTAL.

So this is the html template:

<form [formGroup]="form">
  <div>
  <input type="text" formControlName="client" placeholder="client">
  </div>

  <button type="button" (click)="addPublisher()">Add Publisher</button>

  <div formArrayName="publishers">
    <div *ngFor="let item of publishers; let i = index;">
      <div [formGroupName]="i">
        <input type="number" formControlName="max" placeholder="max">
        <input type="number" formControlName="min" placeholder="min">
        <input type="text" formControlName="total" placeholder="total">
      </div>
    </div>
  </div>

</form>

And this is the ts that matters. I'm subscribing to changes in the publishers, and updating the row only if the change is other than a row being added or deleted.

ngOnInit() {
    (this.form.get('publishers') as FormArray).valueChanges
      .map((publishers: any[]) => {
        if (this.totalPublishers === publishers.length) {
          publishers.forEach((publisher, index) => {
            console.log(`update publishers ${index}`);
            this.updatePublisher((this.form.get('publishers') as FormArray).get([index]) as FormGroup);
          });
        } else {
          console.log(`update total from ${this.totalPublishers} to ${publishers.length}`);
          this.totalPublishers = publishers.length;
        }
      })
      .subscribe();
  }

And to update the value, I do this

private updatePublisher(publisher: FormGroup) {
    this.updateTotals(publisher);
  }

  private updateTotals(publisher: FormGroup) {
    const max = publisher.get('max').value;
    const min = publisher.get('min').value;
    if (max && min) {
      console.log(max, min);
      const total = max - min;
      publisher.get('total').setValue(total);
    }
  }

If I execute this, when I update the first field (max) it checks the value, and as min does not exist yet, nothing happens. Correct. Then when I edit the second value (min), this updateTotals is executed a zillion times, total is calculated at the end and updated in the field, but then if I try to edit those fields again and update the values nothing happens.

Any idea why this is happening?

Thanks.

2
  • what is your expectation. Currently your facing issue because addPublisher() method has only the min, max,total as the form controls Commented Jun 18, 2017 at 5:35
  • if you test the plunkr you will see that the total is calculated the first time, although the updateTotals is executed and awful load of times, and then is like the subscribe is cancelled or something because when you try to update MIN or MAX then TOTAL is not updated any more and updateTotals is not executed again Commented Jun 18, 2017 at 5:41

1 Answer 1

1

When you call setValue valueChange event is fired within updateValueAndValidity. One option should help you

publisher.get('total').setValue(total, { emitEvent: false });

this way your valueChange handler won't be executed infinitely.

Fixed Plunker

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.