5

I have two radio button groups to which I have added angular form controls. The issue I am running into is when I add the controls the radio button groupings are disappearing. In addition, when I inspect the radio button, its name attribute is also disappearing. The effect is that I can no longer tab properly between the different radio button groups. How can I fix this?

Example: https://stackblitz.com/edit/angular-qdqnmo

TS:

import { Component, OnInit } from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit {
  formData = {
          "questions": [
            {
              "refCode": "Question1",
              "answers": [
                {
                  "refCode": "Question1Answer1",
                  "selected": true
                },
                {
                  "refCode": "Question1Answer2",
                  "selected": false
                }
              ]
            },
            {
              "refCode": "Question2",
              "answers": [
                {
                  "refCode": "Question2Answer1",
                  "selected": false
                },
                {
                  "refCode": "Question2Answer2",
                  "selected": false
                },
                {
                  "refCode": "Question3Answer3",
                  "selected": true
                }
              ]
            }
          ]
        };

  formGroup: FormGroup;

  ngOnInit() {
    const group = {};

    this.formData.questions.forEach(question => {
      group[question.refCode] = new FormControl();
    });

    this.formGroup = new FormGroup(group);
  }
}

HTML:

<h2>Normal Buttons:</h2>
<div *ngFor="let question of formData.questions; index as i;">
  <h3>Group {{i + 1}}:</h3>
  <div>
    <div *ngFor="let answer of question.answers" >
      <input type="radio" id="answer.refCode" [checked]="answer.selected" 
      [name]="question.refCode" [value]="answer.refCode" >
      <label for="answer.refCode">{{answer.refCode}}</label>  
    </div>
  </div>
  --------------------------------------------------------------------
</div>

<h2>Angular Buttons:</h2>
<div *ngFor="let question of formData.questions; index as i;">
  <h3>Group {{i + 1}}:</h3>
  <div [formGroup]="formGroup">
    <div *ngFor="let answer of question.answers" >
      <input type="radio" id="answer.refCode" [checked]="answer.selected" 
      [name]="question.refCode" [value]="answer.refCode" 
      [formControlName]="question.refCode">
      <label for="answer.refCode">{{answer.refCode}}</label>  
    </div>
  </div>
  --------------------------------------------------------------------
</div>

Module:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';

import { AppComponent } from './app.component';

@NgModule({
  imports:      [ BrowserModule, FormsModule, ReactiveFormsModule ],
  declarations: [ AppComponent ],
  bootstrap:    [ AppComponent ]
})
export class AppModule { }
AT82
  • 71,416
  • 24
  • 140
  • 167
  • You’re not doing anything with your answers in your form correct? – MikeOne Nov 15 '19 at 18:02
  • what is the issue, I'm having trouble understanding? What is failing in the stackblitz example? Also, by the way, please provide a [mcve] in the question itself. Stackblitz is great!! But this question becomes useless in the future if (when) the link dies. – AT82 Nov 15 '19 at 18:19
  • Hi I added the code snippet. The plan is to add form validation in the future, hence why I've added the form controls. The specific issue is that when I add the form control to the template, it is removing the name attribute on the radio buttons. This causes the radio buttons to not be properly keyboard accessible anymore via tabbing and arrow keys. You can see the difference between the Normal Buttons section (correct) and the Angular Buttons section (incorrect). I hope that helps clarify the issue. Thanks – Andrew Guerra Nov 15 '19 at 18:56

1 Answers1

3

Off-topic: Interesting question, hadn't noticed this before!

Using attribute binding instead of property binding seems to solve that issue! With that you get the actual name attribute in the field, just like "normal" buttons.

But... you have another upcoming issue, so let's tackle that too, which you would eventually run into anyway.

But first, use attribute binding instead:

Use:

[attr.name]="question.refCode"

instead of:

[name]="question.refCode"

Then on to your other issue. Sure when using [checked] in your template, it looks checked, but actually the form value is not set until you interact with the radio buttons. So remove [checked] and instead set the value to the form control instead. That means you are looking for the answer with selected property which is true (if exists), but you want to use refCode as the value instead. Then I suggest the following:

this.formData.questions.forEach(question => {
  const preselected = question.answers.find(x => x.selected === true)
  group[question.refCode] = new FormControl((preselected && preselected.refCode) || null);
});

Your forked STACKBLITZ

AT82
  • 71,416
  • 24
  • 140
  • 167