0

Good evening,

I have built a construct with reactive forms. There is a cocktail array which includes an ingredient array. This should be projected in my reactive form called existingFlavForms. The issue is, I can't get access to the nested ingredient formArray.

this.existingFlavForm = this.fb.group({
          flavs: this.fb.array([])
        });


for (let i = 0; i < this.cocktails.length; i++) {
      this.existingFlavForms.push(this.fb.group({
        id: [this.cocktails[i].id],
        c_name: [this.cocktails[i].c_name],
        mark: [this.cocktails[i].mark],
        imgUrl: [this.cocktails[i].imgUrl],
        ingrs: this.fb.array([
            {ingr: [this.cocktails[i].ingr]}
          ]
        )
      }));
    }

This is the template script, where I try to access everything.

<form [formGroup]="existingFlavForm">
  <div formArrayName="flavs">
    <div *ngFor="let flav of existingFlavForms.controls; let i=index">
      <mat-expansion-panel class="myPanel">
        <mat-expansion-panel-header>
          <mat-panel-title>
            <h3 class="text-info"> {{flav.value.c_name}} </h3>
          </mat-panel-title>
          <mat-icon class="mr-lg-3 mt-lg-2">settings</mat-icon>
          <mat-icon class="mr-lg-3 mt-lg-2" (click)="deleteCocktail()">delete</mat-icon>
        </mat-expansion-panel-header>
        <div class="row">
          <div [formGroupName]="i">
            <div formArrayName="ingrs">
              <p *ngFor="let ingr of flav[i].controls.ingrs.controls;">
                {{ingr.i_name}}
              </p>
            </div>
          </div>
        </div>
      </mat-expansion-panel>
    </div>
  </div>
</form>

I searched in similar questions, but can't find a proper solution. The data is there and fully initialised.

This says the browser console.. "TypeError: undefined is not an object (evaluating '_v.context.$implicit[_v.context.index].controls')"

Best regards!

I have now added a basic stackblitz, which shows the data structure in general with dummy data. https://stackblitz.com/edit/angular-l3ghac

3
  • which line does it show the error message in console? Commented Feb 25, 2019 at 21:23
  • in your for loop you are pushing to existingFlavForms, but that is a formGroup not a formArray, so it doesn't have a push method. Commented Feb 25, 2019 at 21:25
  • TypeError: undefined is not an object (evaluating _v.context.$implicit[_v.context.index].controls') is in line <div formArrayName="ingrs"> but if I remove the following <p> element, I don't get any errors. so it's the line where iteration takes place.. Commented Feb 25, 2019 at 21:28

2 Answers 2

1

I found the solution:

Problem was the initializing of the nested FormArray.

with this could snippet work it for me:

 initExistingFlavForm() {
this.clearArray();
for (let i = 0; i < this.cocktails.length; i++) {
  this.existingFlavForms.push(this.fb.group({
    id: [this.cocktails[i].id],
    c_name: [this.cocktails[i].c_name],
    mark: [this.cocktails[i].mark],
    imgUrl: [this.cocktails[i].imgUrl],
    liqs: this.fb.array([])
  }));
}
this.fillNestedIngredient();

}

fillNestedIngredient() {
for (let i = 0; i < this.cocktails.length; i++) {
  const ingrFormArray = this.existingFlavForm.get('flavs')['controls'][i].get('liqs') as FormArray;
  for (let c = 0; c < this.cocktails[i].ingr.length; c++) {
    ingrFormArray.push(this.fb.group({
      id: [this.cocktails[i].ingr[c].id],
      i_name: [this.cocktails[i].ingr[c].i_name],
      ml_bottle: [this.cocktails[i].ingr[c].ml_bottle],
    }));
  }
}

}

Accessing in html works as usual with an outer *ngFor:

<div formArrayName="liqs">
            <div *ngFor="let ingr of getIngredients(flav); let j = index" [formGroupName]="j">
            </div>
          </div>
Sign up to request clarification or add additional context in comments.

Comments

0

Your element is flav, so calling flav[i] in your iteration is redundant. In your inner for-loop, replace flav[i].controls.ingrs.controls with flav.controls.ingrs.controls.

i.e.

<p *ngFor="let ingr of flav.controls.ingrs.controls;">
    {{ingr.i_name}}
</p>

5 Comments

I agree with the redundant iteration, thanks. But nevertheless this is not the wanted behaviour. It seems that I got with your code snippet the object ingrs as a whole and not the individual ingredient elements where I can access their attributes like "i_name"
In that case, I think what you were trying to do is the following:flav.controls.ingrs not flav.controls.ingrs.controls.
Try this: <p *ngFor="let ingr of flav.controls.ingrs;"> {{ingr.i_name}} </p>
"Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays."
At this point I need to see your data structure to fix the problem. If you could update your question with sample data, then I will take a look.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.