1

Expected Behavior: A set of multiple choice questions is generated from a json file. Each question should consist of multiple options in the form of radio inputs. You should only be able to select one option at a time.

Expected Behavior -

Expected Behavior

Actual Behavior: Everything looks correct until you click on the radio buttons and then click on a different one and it wont deselect the previous one. You can end up selecting every single option if you keep clicking and you cant deselect any of them.

Actual Behavior -

Actual Behavior

Code Breakdown: The base of it is the Review component where we loop through an array of Questions and generate a Question Component for each. We also build the FormGroup and pass it along. Each Question component generates a number of Option components in the exact same manner. The Option components each consist of a <input type="radio"> and a <label>

stackblitz.com/edit/angular-dynamically-generated-radio-buttons

Observations: In the html for the Option component if I remove [formControlName]="name" from the <input> then it corrects the issue i'm having, but that's integral to Reactive Forms. I must be doing something wrong here specifically, but for the life of me I cant figure it out. Its behaving like each option has its own form control, or at least how I imagine that would work.

Below you can see a log of the formgroup, aswell as the html for Question 1: Options 1&2. As far as I can tell it is as it should be. Help please!

Log of FormGroup -

Log of FormGroup

html of Question1, Options1&2 -

html of Question1, Options1&2

2 Answers 2

1
<div class="form-check" [formGroup]="form">
    <input class="form-check-input"  type="radio" [id]="id" [value]="option.letter" [name]="name" #op [formControlName]="name" >
    <label class="form-check-label" [for]="id" >
    {{option.text}}
  </label>
</div>

import { Component, OnInit, Input, ViewChild, ElementRef, AfterViewInit, Renderer2 } from '@angular/core';
import { Question } from '../../models/question';
import { Option } from '../../models/option';
import { FormGroup } from '@angular/forms';

@Component({
  selector: 'app-option',
  templateUrl: './option.component.html',
  styleUrls: ['./option.component.scss']
})
export class OptionComponent implements OnInit, AfterViewInit {
  @Input() question: Question;
  @Input() option: Option;
  @Input() form: FormGroup;
  @ViewChild('op') op: ElementRef;
  id:string;
  name:string;

  constructor(
    private renderer: Renderer2
  ) { }

  ngOnInit() {
    this.id = `${this.question.number}${this.option.letter}`;
    this.name = `${this.question.number}`;
  }
  ngAfterViewInit() {
    this.renderer.setProperty(this.op.nativeElement, 'name', this.name);

  }
}

code shared should solve your issue.

it's happening because for some reason angular isn't writing the name attribute on the radio button.

So this code is explicitly writing it.

Sign up to request clarification or add additional context in comments.

Comments

0

Rahul's patch works good, but what I ended up doing was to just switch to using angular-material elements. In hindsight, it is probably a good idea to use Angular Material elements when you are working with Angular. But for those who cant for whatever reason, his fix works.

Here's what my code looks like with angular material:

OptionComponent html

<div>
  <mat-radio-button [value]="option.letter" >
    {{option.text}}
  </mat-radio-button>
</div>

QuestionComponent html

<div [formGroup]="form">
  <mat-radio-group [formControlName]="name">
    <label>{{question.label}}</label>
    <ng-template #options_anchor></ng-template>
  </mat-radio-group>
</div>

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.