'Get Angular formArrayName Index Values in Template

Need help on accessing Angular formArray object values in the template. I could add and remove items from the formArray group

MINIMAL EXAMPLE

Component File

...
import { FormControl, FormGroup, FormBuilder, FormArray } from '@angular/forms';

form: FormGroup;
constructor(private fb: FormBuilder) { }

ngOnInit(): void {
  this.form = this.fb.group({
    candidateNumber: '',
    subjectGrade: this.fb.array([])
  })
}

get subjectGradeForms() {
  return this.form.get('subjectGrade') as FormArray
}

addSubjectGrade() {
  const subjectGrade = this.fb.group({
    subject: [],
    grade: []
  })
  this.subjectGradeForms.push(subjectGrade);
}

removeSubjectGrade(i) {
  this.subjectGradeForms.removeAt(i)
}

HTML Template File

...
<form class="kt-form" id="kt_form" [formGroup]='form'>
  <div class="form-group">
    <label for="candidateNumber">Candidate Number</label>
    <input formControlName="candidateNumber" class="form-control" type="text" required=""> 
  </div>

  <div class="row" formArrayName='subjectGrade'>
    <div class="row" *ngFor="let subjectGrade of subjectGradeForms.controls; let i=index;" [formGroupName]="i">
      <div class="form-group">
        <label for="subject">Subject Name</label>
        <select class="form-control" formControlName="subject" required="">
          <option *ngFor="let subject of subjectNames" [value]="subject">{{ subject }}</option>
        </select>
      </div>

      <div class="form-group">
        <label for="grade">Subject Grade</label>
        <select class="form-control" formControlName="grade" required="">
          <option *ngFor="let grade of subjectGrades" [value]="grade">{{ grade }}</option>
        </select>
      </div>
    </div>
  </div>
</form>

Challenge/Problem Part [in the HTML Template File]

<div class="kt-wizard-v2__review-content">
  Candidate Number: {{ form.value.candidateNumber }}<br/>  <!-- works as desired with right output-->
  Subject: {{ subjectGrade.value.subject[0] }}<br/>  <!-- does NOT works as desired gives tscript error -->
  Subject: {{ subjectGrade[0].subject }}<br/>  <!-- does NOT works as desired gives tscript error -->
  Subject: {{ form.value.subject[0] }}<br/>  <!-- does NOT works as desired gives tscript error -->
  Subject: {{ form.value.subjectGrade[0].subject }}<br/>  <!-- does NOT works as desired gives tscript error -->
  Subject: {{ form.value.subjectGrade }}<br/>  <!-- does NOT works as desired gives tscript object as output -->
</div>

Form Value Output

value: {{ form.value | json }}
value: {"candidateNumber": "12000", 
        "subjectGrade": [ { "subject": "axb", "grade": "b" }, { "subject": "bxb", "grade": "b" } ] 
       } 

Feel I'm missing something basic, but I cannot see what.

EDIT From this form.value | json output

{"candidateNumber": "12000", 
 "subjectGrade": [ { "subject": "axb", "grade": "b" }, 
                   { "subject": "bxb", "grade": "b" } ]
} 

I want to be able to get the values of the "subject" keys and the values of the "grade" keys.

So, Subject: {{ what_ever_is_here }} should output axb and Grade: {{ what_ever_is_here }} should output b. [At least for the 1st iteration]



Solution 1:[1]

Isn't your index here, on this line:

 <div class="row" *ngFor="let subjectGrade of subjectGradeForms.controls; let i=index;" [formGroupName]="i">

that i?

You must then add the button that calls the function which removes an item under that ngfor block and call:

removeSubjectGrade(i)

Is this what you meant or is your problem with the component functions?

Solution 2:[2]

This is how I implemented FormArray for checkboxes in my code,
HTML

<div formArrayName="healthQuestions">
                <div
                  *ngFor="let questionControl of cdqRequestFG.controls.questions.controls.healthQuestions.controls; let i=index;"
                  nxRow>
                  <div class="centre-align" nxCol="12,6,4,3">
                    <nx-radio-group [formControlName]="i" style="display: flex;">
                      <nx-radio style="padding:15px;" [labelSize]="'small'" nxValue="YES">yes
                      </nx-radio>
                      <nx-radio style="padding:15px;" [labelSize]="'small'" nxValue="NO">No
                      </nx-radio>
                    </nx-radio-group>
                  </div>
                  <div nxCol="12,6,8,9">
                    <p style='font-size:18px; text-align: left'>{{i+1}} - {{rgaQuestions[i].description}}</p>
<!-- to display the contents of rgaQuestions, to display question number i+1 used since index begin at 0-->
                  </div>
                </div>
              </div>

Component.ts

healthQuestionsFC: FormArray;
this.healthQuestionsFC = new FormArray([], Validators.required);

// read the arry result to Model Array
//the array items are stored in array rgaQuestions[], user response for each item in this array is obtained from below loop
this.rgaQuestions.forEach(
      (val, index) => {
//      **getting Index value from template**
        const ansC = this.healthQuestionsFC.get(index + '');
        const question = new QuestionResp(val.questionId + '', ansC.value);
        questionList.push(question);
      });

//clear the array
clearFormArray = (formArray: FormArray) => {
    while (formArray.length !== 0) {
      formArray.removeAt(0);
    }
  }

Solution 3:[3]

For me it's work fine

get t() { return this.questions.controls.chooses as FormArray; }

t.at(i).value

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 SebastianG
Solution 2
Solution 3 Ndiaga GUEYE