AJ-
AJ-

Reputation: 1783

Angular - FormBuilder, how to group multiple Form Controls

I use Formbuilder to create a FormGroup:

myForm = this.fb.group(
            {
                title: [""],
                fixed_grade1: [""],
                fixed_value1: [""],
                fixed_grade2: [""],
                fixed_value2: [""],
                fixed_grade3: [""],
                fixed_value3: [""],
                fixed_grade4: [""],
                fixed_value4: [""]
            });

all the fixed_grade and fixed_value are inputs and dropdowns.

I have 4 pairs of them, and this works correctly.

But now I would like to group these, so I don't have to access each value in my controller one by one, with myForm.get("fixed_grade1").value for each one.

But I would like that all these value are grouped in an array like:

myArray: [{grade, value}, [grade, value}...]

so I can access their value by: myArray[0].grade

Instead of mapping each single value to a new array, I saw there is a FormArray in FormBuilder, I just don't seem to be able to implement it correclty.

What would be the correct syntax to achieve what I described, having exactly 4 pairs of grade/score, and also it's important that in my final array with all these pairs grade/score, I have only the values that are not undefined, so if in my form the user only fills one pair grade/score, then my myArray.length will be 1.

Upvotes: 2

Views: 9823

Answers (1)

SiddAjmera
SiddAjmera

Reputation: 39432

You have defined your FormGroup wrong. Your FormGroup should have had a FormArray of FormGroups. Inside each of these FormGroups there should have been two FormControls for grade and value.

Change your form to this:

const grades = [
  {grade: 'Grade 1', value: 'Value 1'},
  {grade: 'Grade 2', value: 'Value 2'},
  {grade: 'Grade 3', value: 'Value 3'},
  {grade: 'Grade 4', value: 'Value 4'}
]

myForm = this.fb.group({
  title: [],
  grades: this.fb.array(this.grades.map(grade => this.fb.group({
    grade: [grade.grade],
    value: [grade.value]
  }))),
});

// OR

myForm = this.fb.group({
  title: [],
  grades: this.fb.array(this.grades.map(grade => this.fb.group({
    grade: [],
    value: []
  }))),
});
...
get gradesArray() {
  return (<FormArray>this.myForm.get('grades')).controls;
}
...
getArrayGroupControlByIndex(index) {
  return (<FormArray>this.myForm.get('grades'))
    .at(index);
}

This is how you'll use it in the template:

<form [formGroup]="myForm">
  <input type="text" formControlName="title">
  <br>
  <div formArrayName="grades">
    <div *ngFor="let gradeGroup of gradesArray; let i = index;">
      <div [formGroupName]="i">
        Group {{ i + 1 }}
        <input type="text" formControlName="grade">
        <input type="text" formControlName="value">
      </div>
      <br>
    </div>
  </div>
</form>

Here's a Sample StackBlitz for your ref.

Upvotes: 3

Related Questions