-2

Here's how I bind data received from an API to my Form Group/Array, on the CTOR:

  this.api.getRecipe(id).subscribe((data) => {
    this.form = this.fb.group({
      nome: [data.nome, [Validators.required]],
      ingredienti: this.fb.group({
        acqua: [data.ingredienti.acqua, [Validators.required]],
        farine: this.fb.array(
          data.ingredienti.farine.map(item => (
            this.fb.group({
              quantita: [item.quantita, [Validators.required]],
              nome: [item.nome]
            })
          ))
        )
      })
    });
  });

And this is how I iterate FormArray's farine items on View:

  <mat-card *ngFor="let item of form.get('ingredienti').get('farine')['controls']; let itemIndex = index">
    <div [formGroupName]="itemIndex">
      <mat-form-field>
        <input matInput type="number" formControlName="quantita" />
      </mat-form-field>
      <mat-form-field>
        <input matInput type="text" formControlName="nome" />
      </mat-form-field>
    </div>
    <button type="button" (click)="addFarina()">Add</button>
  </mat-card>     

Now, clicking on addFarina(), I'd like to simply add a new item on FormArray's farine. I did this:

  addFarina() {
    let farineForm = this.form.value.ingredienti.farine;
    let farineFormControls = this.form.get('ingredienti').get('farine')['controls'];

    if (farineForm.length < 4) {
      const farina = this.fb.group({
        quantita: [null, [Validators.required]],
        nome: ['']
      })

      farineForm.push(farina);
      farineFormControls.push(farina);
    }
  } 

But I feel like I'm not really using the potentially of this framework, updating manually both this.form items and related farine's controls.

What's the best way to "edit" the data on form and subscribe edits also on View? So I don't need to manually manage the link between Data and View.

markzzz
  • 47,390
  • 120
  • 299
  • 507
  • Acutally you no need farineForm.push(farina) this code ,After adding formGroup to formArray you can read the value by farineFormControls.value – Chellappan வ Mar 22 '22 at 10:44
  • take a look at this answer https://stackoverflow.com/questions/53708499/dynamic-form-using-ngfor-and-submitting-values-from-it/53710438#53710438 – Marshal Mar 22 '22 at 13:24
  • @Chellappanவ that's not really true. If I don't do `farineForm.push(farina)`, than when I send data via API (i.e. `this.api.addRecipe(this.form.value).subscribe(...)`), the form's values are not updated/present. That's why I update both, updating both FormControls and form value... – markzzz Mar 23 '22 at 08:25

1 Answers1

2

You should call push method on formArray control. Since you are pushing new FormGroup inside normal array underlaying FormGroup is not get updated.

    addFarina() {
        let farineForm = this.form.value.ingredienti.farine;
        let farineFormControls = this.form.get('ingredienti').get('farine') as FormArray;
    
        if (farineForm.length < 4) {
          const farina = this.fb.group({
            quantita: [null, [Validators.required]],
            nome: ['']
          })
    
          farineFormControls.push(farina);
        }
        console.log(this.form.get('ingredienti').value);
      } 

Now you should be able to access all formValue like this no need to push values inside array manually.

this.api.addRecipe(this.form.value).subscribe(...)

Working Stackblitz

Chellappan வ
  • 23,645
  • 3
  • 29
  • 60
  • it doesn't work on my side. if I farineFormControls.push(farina), this.form.value later is not updated – markzzz Mar 23 '22 at 10:09
  • this line you need to change let farineFormControls = this.form.get('ingredienti').get('farine')['controls']; ===> let farineFormControls = this.form.get('ingredienti').get('farine') as FormArray; – Chellappan வ Mar 23 '22 at 10:11
  • you were right! works perfect now, thanks! is there a way to get the size of FormArray? so don't need let farineForm = this.form.value.ingredienti.farine; anymore... – markzzz Mar 23 '22 at 10:16
  • I see SO didn't place Bounty to you automatically. Sorry. I've added to it right now :) – markzzz Mar 29 '22 at 09:31