Search code examples
angularangular4-forms

How to dynamically set values in Angular2/4 FormArray fields?


I got a dynamic table that can add rows to it. How do I dynamically set the data in col 3? I am using form builder to create my forms and has a method that accepts to dynamically insert the rows in a table. When I write something in col1, I subscribe to change and compute the sum on the two cols to put it on the third col.

    public sumRow() {
        this.myForm
          .get('rows')
          .valueChanges
          .subscribe((val) => {

             // latest edit
             val.foreach((item) => {
                item.col3 = item.col1 + col2;
                // But this one does not fill the col3 but 
                // it already giving the correct values
             });

             //loop to the val instead 

             // const ctrl = this.myForm.controls['rows'];
             // ctrl.controls.forEach((field) => {
             // const col1 = parseInt(field.get('col1').value, 10);
             // const col2 = parseInt(field.get('col2').value, 10);
             // const sum = col1 + col2;
             // How to set these values to col3?
             // Doesn't work: field.get('col3').setValue(sum);
        });
    }

  public createForm() {
    this.myForm = this.fb.group({
      name: ['', Validators.required],
    });
  }

  public pushRowItems(items) {
    this.myForm.addControl('rows', this.fb.array([items]));
  }

  public initItemRows() {
    return this.fb.group({
      col1: 0,
      col2: 0,
      col3: 0,
    });
  }

  public ngOnInit() {
    this.createForm();
    this.pushRowItems(this.initRowItems());
    this.sumRow();
  }

Solution

  • What I would do, is to skip the valueChanges and use one-way-binding with ngModel for the sum of your columns. Not knowing how your template looks like, you have a couple of options:

    Show a disabled input field as the third column, or then use a hidden input field and instead show for example a <p>.

    If you use a disabled field, you need to use getRawValue() to get the values of the disabled fields.

    Usually I wouldn't recommend using ngModel together with reactive forms, but in this case it's fine, since we don't use it bind it to a separate variable in TS.

    So here's how your code would look like with the hidden option:

    <table formArrayName="rows">
      <tr *ngFor="let item of myForm.controls.rows.controls; let i = index" [formGroupName]="i">
        <td><input type="number" formControlName="col1"></td>
        <td><input type="number" formControlName="col2"></td>
        <td> <input type="number" hidden formControlName="col3" [ngModel]="item.controls.col1.value + item.controls.col2.value"></td>
        <td><p>{{item.controls.col3.value}}</p></td>
      </tr>
    </table>
    

    StackBlitz