I am working on an Angular 12 application. It has a table with multiple rows populated dynamically. Each row has four columns. The third column has radioButton Yes No as shown.
- Desired Output: Example, if the table has three rows and I want to select Yes Radio button in first row, No in second and I don't want to select any in third row, it should be allowed.
- Actual Output: It is letting me select only one row with either Yes or No.
My html to be populated dynamically : marks-input-component.html
<ng-container *ngIf="!!markForm" [formGroup]="markForm">
<ng-container *ngIf="inputType === inputEnum.RADIO_BUTTON">
<fieldset>
<ng-container *ngFor="let item of options">
<div >
<input type="radio" [formControl]="oneInputControl" id="{{ item.markId }}-{{ item.id }}" [value]="item.id">
<label for="{{ item.markId }}-{{ item.id }}"> {{ item.option }}</label>
</div>
</ng-container>
</fieldset>
</ng-container>
<br>
My dynamic ts file : marks-input-component.ts
export class MarksInputComponent implements OnInit{
@Input() inputType: string;
@Input() markId: number;
@Input() markForm: FormGroup;
options: MarkOption[];
ngOnInit(): void {
super.ngOnInit();
this.initOptions();
this.connectListeners();
}
private connectListeners() {
this.onOneInputChange();
}
private onOneInputChange() {
this.oneInputControl.valueChanges.pipe(
takeUntil(this.destroyed$),
tap((value) => {
const id = parseInt(value);
if (id) {
const option = this.options.find(v => v.id === id);
option ? this.markForm.controls.mark.patchValue(option.mark) : this.markForm.controls.mark.patchValue(undefined);
} else {
this.oneInputControl.patchValue(-1, { onlySelf: true, emitEvent: false });
this.markForm.controls.mark.patchValue(undefined);
}
})
).subscribe();
}
get responses() {
return this.markForm.controls.responses as FormArray;
}
get oneInputControl() {
const f = this.responses.controls[0] as FormGroup;
return f.controls.markId as FormControl;
}
}
The html page: marks-component.html
<ng-container *ngFor="let markForm of allMarkForms.controls">
<ng-container *ngFor="let markResponse of manualMarks; let rowNum = index">
<ng-container *ngIf="markForm.controls.markId.value === markResponse.markId">
<tr id="manual-mark-response-row-{{ rowNum }}" }}">
<td id="mark-id-{{ rowNum }}">{{ markResponse.markIdText }}</td>
<td id="mark-text-{{ rowNum }}">{{ markResponse.markText }}</td>
<td id="mark-mark_description-{{ rowNum }}">
<!-- marks input component -->
<app-dynamic-input
[inputType]="markResponse.inputType"
[markId]="markResponse.markId"
[markForm]="markForm"></app-dynamic-input>
</td>
<td id="mark-mark-{{ rowNum }}">
<ng-container *ngIf="markResponse.inputType === inputEnum.RADIO_BUTTON">
{{ markForm.controls.mark.value }}
</ng-container>
</td>
</tr>
</ng-container>
</ng-container>
</ng-container>
CodePudding user response:
You're assigning the same FormControl
to each input, so they will act as a single input group. In reality, you need a unique FormControl
for each yes / no pair.
Here's a simple example of a form with three yes / no questions
export class OneComponent {
myFormGroup = new FormGroup({
q1: new FormControl(),
q2: new FormControl(),
q3: new FormControl(),
});
get allControlNames() {
return Object.keys(this.myFormGroup.controls);
}
}
<form [formGroup]="myFormGroup">
<ng-container *ngFor="let controlName of allControlNames">
<label>
<input type="radio" [value]="true" [formControlName]="controlName" />
<span>YES</span>
</label>
<label>
<input type="radio" [value]="false" [formControlName]="controlName" />
<span>NO</span>
</label>
<br />
</ng-container>
</form>
Use formControlName=""
to select a specific FormControl
from the encapsulating FormGroup
.
CodePudding user response:
In the input type radio, I was missing unique name field for each yes / no pair. Adding name="{{ item.markId }}-test" this worked for me.
<input type="radio" name="{{ item.markId }}-test" [formControl]="oneInputControl" id="{{ item.markId }}-{{ item.id }}" [value]="item.id">