1

I have the following JSON which I wish to map out to a form:

{
  "lineItemId": 0,
  "count": 0,
  "fixtures": [
    {
      "fixtureId": 0,
      "fixtureName": "string",
      "total": 0,
      "completed": 0,
      "guestDetails": [
        {
          "id": 0,
          "forename": "string",
          "surname": "string",
          "email": "string",
          "telephone": "string",
          "specialInstructions": "string",
          "completed": true,
          "dietaryRequirements": [
            {
              "id": 0,
              "name": "string",
              "isRequired": true
            }
          ]
        }
      ]
    }
  ]
}

I then have the following working typescript which maps it out to formbuilder:

this.myForm = this.fBuilder.group({
   guestDetailsForm: this.fBuilder.array([])
});

this.httpService.getGuestDetails(this.eventId, this.passedIdValue)
   .subscribe(data => {
      this.fixturesArray = data.fixtures;
      console.log(this.fixturesArray);
      this.fixturesArray.forEach(fixturesArrayElement => {
          this.guestDetailsArray = fixturesArrayElement.guestDetails;
          this.guestDetailsArray.forEach(element => {
            (<FormArray>this.myForm.get('guestDetailsForm')).push(this.fBuilder.group({
            id: [element.id],
            forename: [element.forename],
            surname: [element.surname, Validators.required],
            email: [element.email],
            telephone: [element.telephone],
            dietaryRequirements: [element.dietaryRequirements]
          }));
      });
});
},
   error => alert(error),
   () => console.log(""));

I can list out the forename, surname, email etc all fine but it won't display the text fields for the "dietaryRequirements" data in the following template. I assume it's to do with my inner *ngFor loop but nothing seems to work. Any help? :)

<div class="generalForm" formArrayName="guestDetailsForm">
  <div *ngFor="let guest of myForm.controls.guestDetailsForm.controls; let i=index" [ngClass]="{'guestForm show' : viewingGuestId == i, 'guestForm hide' : viewingGuestId != i}">
     <div [formGroupName]="i">
        <input type="hidden" formControlName="id" />
        <ol>
           <li class="inputQuestion">
             <label>Forename</label>
             <input type="text" formControlName="forename" />
            </li>
            <li class="inputQuestion">
              <label>Surname</label>
              <input type="text" formControlName="surname" />
              <div [hidden]="myForm.controls.guestDetailsForm.controls[i].controls.surname.valid" class="inlineError">Required
              </div>
            </li>
            <li class="inputQuestion">
                <label>Email</label>
                <input type="text" formControlName="email" />
            </li>
            <li class="inputQuestion">
                <label>Telephone</label>
                <input type="text" formControlName="telephone" />
            </li>
            <li class="dietaryRequirementsQuestion" formArrayName="dietaryRequirements">

               <div *ngFor="let meals of myForm.controls.guestDetailsForm.controls[i].controls.dietaryRequirements; let x=index">
                  <div [formGroupName]="x">
                     <input type="text" formControlName="name" />
                  </div>
               </div>
             </li>
          </ol>
        </div>
      </div>
    </div>

1 Answer 1

5

I would create FormArray instead of just array for dietaryRequirements

buildFormArrayOfGroupsFromArr(arr) {
  return this.fBuilder.array(arr.map(x => this.fBuilder.group(x)));
}
...

dietaryRequirements: this.buildFormArrayOfGroupsFromArr(element.dietaryRequirements)

After that you write the following html:

<div *ngFor="let meals of myForm.controls.guestDetailsForm.controls[i].controls.dietaryRequirements.controls; let x=index">
  <div [formArrayName]="x">
    <input type="text" formControlName="name" />
  </div>
</div>

You can also have a look at Plunker Example

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

9 Comments

It builds only array of dietaryRequirements
Ah ok, how would I modify this if I wanted to manually put the keys in rather than automatically (for dietaryRequirements)?
Just pass here other array this.buildDietaryRequirements(element.dietaryRequirements)
Oh but I don't want to map it, I want to manually write: Id:, Name:, isRequired:
|

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.