[FIXED] Nested FormGroup in FormArray repeating all radio button values – Angular (UI with PrimeNG)

Issue

Stackblitz

I am working on a form with radio button inputs (using PrimeNg ui but this shouldn’t matter to the question at hand), where each radio button group is being populated by an API into a form group. In my AppComponent I am populating the data, and is how this comes in from the API (static data for sample):

ngOnInit() {
    this.settingsByCategory = [
      {
        categoryName: 'None',
        permissions: [
          {
            id: 1,
            name: 'Test Category 1'
          },
          {
            id: 2,
            name: 'Test Category 2'
          },
          {
            id: 9,
            name: 'Test Category 3'
          }
        ]
      }
    ];

    this.settingForm = this.fb.group({
      settings: this.fb.array([])
    });

    this.setForm();
  }

  setForm() {
    this.settingsByCategory.forEach(i => {
      i.permissions.forEach(p => {
        (this.settingForm.get('settings') as FormArray).push(
          this.fb.group({
            settingId: p.id,
            settingName: p.name,
            permission1: null,
            permission2: null,
            permission3: null
          })
        );
      });
    });
  }

The problem is that when I select a radio button, all groups are selected instead of just one single group.
enter image description here

In my HTML I am using a nested grouping of FormGroup, FormArrayName, and FormControls to populate with the appropriate data. It is a little messy, but I am first trying to work through this issue:

<ng-container>
  <div>
    <form [formGroup]="settingForm">
      <div formArrayName="settings" class="perm-grid">
        <div *ngFor="let setting of settings.controls; index as i">
          <div [formGroupName]="i">
            <h2 style="border-bottom: 1px solid #495057; padding-left: 5px">{{ setting.value.settingName }}</h2>
            <ul class="perm-list">
              <li class="radio-grid">
                <div class="radio-grid-row">
                  <div style="margin-left: 5px"></div>
                  <div>Company</div>
                  <div>Area</div>
                  <div>Location</div>
                </div>
                <div class="radio-grid-row">
                  <div style="margin-left: 5px">None</div>
                  <div>
                    <p-radioButton (onClick)="logRadio($event, setting)" name="permission1"
                      formControlName="permission1" [value]=0>
                    </p-radioButton>
                  </div>
                  <div>
                    <p-radioButton (onClick)="logRadio($event, setting)" name="permission2"
                      formControlName="permission2" [value]=0>
                    </p-radioButton>
                  </div>
                  <div>
                    <p-radioButton (onClick)="logRadio($event, setting)" name="permission3"
                      formControlName="permission3" [value]=0>
                    </p-radioButton>
                  </div>
                </div>
                <div class="radio-grid-row">
                  <div style="margin-left: 5px">View</div>
                  <div>
                    <p-radioButton (onClick)="logRadio($event, setting)" name="permission1"
                      formControlName="permission1" [value]=1>
                    </p-radioButton>
                  </div>
                  <div>
                    <p-radioButton (onClick)="logRadio($event, setting)" name="permission2"
                      formControlName="permission2" [value]=1>
                    </p-radioButton>
                  </div>
                  <div>
                    <p-radioButton (onClick)="logRadio($event, setting)" name="permission3"
                      formControlName="permission3" [value]=1>
                    </p-radioButton>
                  </div>
                </div>
                <div class="radio-grid-row">
                  <div style="margin-left: 5px">Edit</div>
                  <div>
                    <p-radioButton (onClick)="logRadio($event, setting)" name="permission1"
                      formControlName="permission1" [value]=2>
                    </p-radioButton>
                  </div>
                  <div>
                    <p-radioButton (onClick)="logRadio($event, setting)" name="permission2"
                      formControlName="permission2" [value]=2>
                    </p-radioButton>
                  </div>
                  <div>
                    <p-radioButton (onClick)="logRadio($event, setting)" name="permission3"
                      formControlName="permission3" [value]=2>
                    </p-radioButton>
                  </div>
                </div>
              </li>
            </ul>
          </div>
        </div>
      </div>
    </form>
  </div>
</ng-container>

With standard inputs, I have used this method and it has worked just fine. Why are all the radiobutton form controls being repeated across groups?

Stackblitz

Solution

That happens because the name of the radio-button group is the same for all categories, so all of them are connected to each other.

You can resolve this issue like the following:

  • Add a suffix/prefix to the group name to distinguish them from each other, e.g. you can add the index i such as name="permission1-{{i}}", so this will be resolved later to name="permission1-0" for category 1 & name="permission1-1" for category 2…etc.
  • The above change will cause another problem related to the used primeNG version, which is: If you define both a name and a formControlName attribute on your radio button, their values must match, and to resolve it you can use formControl instead of formControlName such as: [formControl]="settingForm?.get('settings').controls[i].get('permission1')"

So the radio-botton part of your component template will look like the following:

<div class="radio-grid-row">
  <div style="margin-left: 5px">None</div>
  <div>
    <p-radioButton (onClick)="logRadio($event, setting)" name="permission1-{{i}}"
      [formControl]="settingForm?.get('settings').controls[i].get('permission1')" [value]="0">
    </p-radioButton>
  </div>
  <div>
    <p-radioButton (onClick)="logRadio($event, setting)" name="permission2-{{i}}"
      [formControl]="settingForm?.get('settings').controls[i].get('permission2')" [value]="0">
    </p-radioButton>
  </div>
  <div>
    <p-radioButton (onClick)="logRadio($event, setting)" name="permission3-{{i}}"
      [formControl]="settingForm?.get('settings').controls[i].get('permission3')" [value]="0">
    </p-radioButton>
  </div>
</div>
<div class="radio-grid-row">
  <div style="margin-left: 5px">View</div>
  <div>
    <p-radioButton (onClick)="logRadio($event, setting)" name="permission1-{{i}}"
      [formControl]="settingForm?.get('settings').controls[i].get('permission1')" [value]="1">
    </p-radioButton>

  </div>
  <div>
    <p-radioButton (onClick)="logRadio($event, setting)" name="permission2-{{i}}"
      [formControl]="settingForm?.get('settings').controls[i].get('permission2')" [value]="1">
    </p-radioButton>
  </div>
  <div>
    <p-radioButton (onClick)="logRadio($event, setting)" name="permission3-{{i}}"
      [formControl]="settingForm?.get('settings').controls[i].get('permission3')" [value]="1">
    </p-radioButton>
  </div>
</div>
<div class="radio-grid-row">
  <div style="margin-left: 5px">Edit</div>
  <div>
    <p-radioButton (onClick)="logRadio($event, setting)" name="permission1-{{i}}"
      [formControl]="settingForm?.get('settings').controls[i].get('permission1')" [value]="2">
    </p-radioButton>
  </div>
  <div>
    <p-radioButton (onClick)="logRadio($event, setting)" name="permission2-{{i}}"
      [formControl]="settingForm?.get('settings').controls[i].get('permission2')" [value]="2">
    </p-radioButton>
  </div>
  <div>
    <p-radioButton (onClick)="logRadio($event, setting)" name="permission3-{{i}}"
      [formControl]="settingForm?.get('settings').controls[i].get('permission3')" [value]="2">
    </p-radioButton>
  </div>
</div>

And here is the edited version of your stackbiltz:
https://stackblitz.com/edit/primeng-dynamicdialog-demo-25iydv

Answered By – Amer

Answer Checked By – Candace Johnson (Easybugfix Volunteer)

Leave a Reply

(*) Required, Your email will not be published