FormGroup containing Radio Buttons with an Angular FormArray

11,208

What you need to consider when looping through an array group is the id and name you assign to each one. You currently have your input id and name getting set to the same value in each loop.

You would need to use the i variable you have available to make the id and name for each input a dynamic value, like below:

<div [formGroup]="form">
  <div *ngIf="conditions" formArrayName="conditions">

    <div *ngFor="let condition of conditions.controls; let i=index" [formGroupName]="i">

      <input class="form-control" formControlName="title" type="text" placeholder="title">

      <div class="custom-control custom-radio custom-control-inline">
        <input type="radio" id="{{ 'acceptable' + i}}" formControlName="acceptability"
            class="custom-control-input" [value]="ACCEPTABILITY.ACCEPTABLE">
        <label class="custom-control-label" for="{{ 'acceptable' + i}}">Acceptable</label>
      </div>

      <div class="custom-control custom-radio custom-control-inline">
        <input type="radio" id="{{ 'unacceptable' + i}}" formControlName="acceptability"
            class="custom-control-input" [value]="ACCEPTABILITY.INACCEPTABLE">
        <label class="custom-control-label" for="{{ 'unacceptable' + i}}">Unacceptable</label>
      </div>

    </div>

    <button type="button" class="btn btn-outline-dark btn-block" (click)="addCondition()">
            <i class="fa fa-plus fa-lg mr-3"></i>ADD A NEW CONDITION</button>
  </div>
</div>

<div>
  <pre>{{ form.value | json }}</pre>
</div>

Notice the string interpolation for the name and id attributes. Same goes for the for attribute in the labels.

You may have to play around with this to get is exactly where it needs to be. (I didn't test it thoroughly)

Hope this helps.

Share:
11,208
Sammy
Author by

Sammy

Updated on June 11, 2022

Comments

  • Sammy
    Sammy almost 2 years

    I have the following code that dynamically adds a form group containing a title and two radio buttons to create a condition, effectively providing its title and whether or not it's an acceptable condition:

    export enum Acceptability {
      ACCEPTABLE,
      INACCEPTABLE
    }
    
    export interface Condition {
      title: string;
      acceptability: Acceptability;
    }
    
    export class AddCondition implements OnInit {
    
      form: FormGroup;
      ACCEPTABILITY = Acceptability;
    
      constructor(private fb: FormBuilder) {}
    
      ngOnInit() {
        // build the form
        this.form = this.fb.group({
          conditions: this.fb.array([])
        });
    
      }
    
      get conditions(): FormArray {
        return this.form.get('conditions') as FormArray;
      }
    
      addCondition() {
        this.conditions.push(this.fb.group({
          title: ['', Validators.required],
          acceptability: ['', Validators.required]
        }));
      }
    }
    <div formArrayName="conditions">
      <div *ngFor="let condition of conditions.controls; let i=index" [formGroupName]="i">
        <input class="form-control" formControlName="title" type="text" placeholder="title">
        <div class="custom-control custom-radio custom-control-inline">
          <input type="radio" id="acceptable" formControlName="acceptability" name="acceptability" class="custom-control-input" [value]="ACCEPTABILITY.ACCEPTABLE">
          <label class="custom-control-label" for="acceptable">Acceptable</label>
        </div>
        <div class="custom-control custom-radio custom-control-inline">
          <input type="radio" id="inacceptable" formControlName="acceptability" name="acceptability" class="custom-control-input" [value]="ACCEPTABILITY.INACCEPTABLE">
          <label class="custom-control-label" for="inacceptable">Inacceptable</label>
        </div>
      </div>
      <button type="button" class="btn btn-outline-dark btn-block" (click)="addCondition()">
              <i class="fa fa-plus fa-lg mr-3"></i>ADD A NEW CONDITION</button>
    </div>

    The problem is that when clicking the ADD A NEW CONDITION button, and the new form group appears, every time I select any radio button in the group array, the corresponding radio button of the first array item in the group is the one that gets selected.

  • Sammy
    Sammy over 6 years
    Thank you, but this then produces the following error: If you define both a name and a formControlName attribute on your radio button, their values must match. Ex: <input type="radio" formControlName="food" name="food">
  • Sammy
    Sammy over 6 years
    But then of course, if I go ahead and change formControlName to match it, then I get the error that the control does not exist; which is normal since when I push the new group, I push it with the name acceptability only.
  • R. Richards
    R. Richards over 6 years
    Have you tried it without setting the name attribute at all by removing it?
  • Sammy
    Sammy over 6 years
    Yes, that's where I get Error: Cannot find control with path: 'conditions -> 0 -> acceptability0' which is, I believe, logical, since what I'm pushing up there is acceptability only.
  • R. Richards
    R. Richards over 6 years
    Okay, let me try a few things. I will update the answer when I have something. Sorry about the back and forth!
  • R. Richards
    R. Richards over 6 years
    I have updated the answer. This is working for me. No errors at all. I am able to add to the form array and the radio buttons work as expected. I added a div tag to output the form value, which looks accurate to me, and update when the form values change. Have a look and give this a try.
  • Sammy
    Sammy over 6 years
    Thank you; besides removing name, did you do anything else that I'm not seeing? When you click the "add" button, you do not get the Cannot find control with path... error?
  • R. Richards
    R. Richards over 6 years
    No errors whatsoever. Removing the name was all I really did from the code I originally posted. I pulled your component code into a project I have been playing around with to test this. Works.
  • Sammy
    Sammy over 6 years
    Indeed; I guess removing name and not having formControlName dynamic was the one permutation I did not try. Thank you :)
  • IronWorkshop
    IronWorkshop over 4 years
    This helped alot thank you, I was stuck on it for a while and couldn't work out why. I did have to remove the '[]' expression syntax from my 'value' attribute however. But everything else worked great. Thanks!