Dynamic custom component radio buttons do not have unique name when duplicated

Discussão em 'Angular' iniciado por Mark Hill, Março 7, 2025.

  1. Mark Hill

    Mark Hill Guest

    I have the following form with a set of radio buttons in each section I can only select one of the buttons at any given time.

    It appears that they do not have unique names.

    [​IMG]

    The form is dynamically generated using the following code:

    get anatomicalComplaints(): FormArray {
    return this.childForm.get('dcrr_pc')?.get('pc_anat_loc_compl') as FormArray
    }

    addAnatomicalComplaints() {
    this.anatomicalComplaints.push(this.createNewAnatomicalComplaint())
    }

    removeAnatomicalComplaints(index: number) {
    this.anatomicalComplaints.removeAt(index)
    }

    createNewAnatomicalComplaint() {
    return new FormGroup({
    spinal: new FormControl(''),
    vas: new FormControl(''),
    laterality: new FormControl(''),
    radicular_component: new FormControl(''),
    pc_cas_hist_doc_compl: new FormControl('')
    })
    }


    Each input in the form is a custom component that I have built to make development easier. The code follows here:

    import { CommonModule } from '@angular/common';
    import { Component, forwardRef, Host, Input, OnDestroy, OnInit, Optional, ViewEncapsulation } from '@angular/core';
    import { toSignal } from '@angular/core/rxjs-interop';
    import { ControlValueAccessor, FormControl, NG_VALUE_ACCESSOR, ReactiveFormsModule, FormsModule, AbstractControl, FormGroupDirective, ControlContainer, FormGroup, FormArray } from '@angular/forms';
    import { Subject } from 'rxjs';

    @Component({
    selector: 'app-form-input',
    standalone: true,
    imports: [
    CommonModule
    ],
    templateUrl: './form-input.component.html',
    styleUrl: './form-input.component.scss',
    providers: [
    {
    provide: NG_VALUE_ACCESSOR,
    useExisting: forwardRef(() => FormInputComponent),
    multi: true
    },

    ],
    viewProviders: [
    {provide: ControlContainer, useExisting: FormGroupDirective}
    ]
    })
    export class FormInputComponent implements OnInit, ControlValueAccessor, OnDestroy {

    @Input() placeholder: string = ''
    @Input() type: string = 'text'
    @Input() label: string = ''
    @Input() required: boolean = false
    @Input() minLength: number = 0
    @Input() labelClassList: string = ''
    @Input() classList: string= ''
    @Input() size: string = 'sm'
    @Input() options: string[] = [];
    @Input() selectOptions: any;
    @Input() controlName : string | null = null
    @Input() indexAt : number = 0
    @Input() formType : string = 'horizontal'
    @Input() inputGroup : boolean = false

    protected onTouched: any = () => {}

    private onChange: any = () => {}
    private destroy$ = new Subject<void>()

    control !: AbstractControl

    value: any;

    constructor(public parentForm: FormGroupDirective) {

    }

    ngOnInit() {

    }

    setRadioId = (index: number) => `${this.controlName}${index}`


    writeValue(value: any): void {
    this.value = value
    }

    registerOnChange(fn: any): void {
    this.onChange = fn
    }

    registerOnTouched(fn: any): void {
    this.onTouched = fn
    }

    onInputChange(event: any): void {
    this.value = event.target.value
    this.onChange(this.value)
    }

    ngOnDestroy(): void {
    this.destroy$.next()
    this.destroy$.complete()
    }
    }


    @if(!inputGroup) {
    <div [class]="classList">
    @if(label != '' && formType == 'default') {
    <label>{{label}}</label>
    }
    @if(type == 'text' || type == 'date') {
    <input
    [type]="type"
    [placeholder]="placeholder"
    [value]="value"
    (input)="onInputChange($event)"
    (blur)="onTouched()"
    class="form-control"
    [class.form-control-sm]="size == 'sm'"
    />
    }
    @if(type == 'radio') {
    @for(option of options; track option; let idx = $index) {
    <div class="form-check form-check-inline">
    <input class="form-check-input" [type]="type" [name]="controlName" [id]="setRadioId(idx)" [value]="option">
    <label class="form-check-label" [for]="setRadioId(idx)">
    {{option}}
    </label>
    </div>
    }
    }

    @if(type == 'checkbox') {
    @for(option of options; track option; let idx = $index) {
    <div class="form-check">
    <input [type]="type" class="form-check-input" [name]="controlName">
    <label class="form-check-label">
    {{option}}
    </label>
    </div>
    }
    }

    @if(type == 'select') {
    <select class="form-control" [class.form-control-sm]="size == 'sm'" (input)="onInputChange($event)"
    (blur)="onTouched()">
    <option value="">--Payer--</option>
    <option *ngFor="let o of selectOptions" [value]="o">{{o}}</option>
    </select>
    }

    @if(type == 'textarea') {
    <textarea class="form-control" [class.form-control-sm]="size == 'sm'" rows="5" width="100%"></textarea>
    }
    </div>
    }

    @if(inputGroup) {
    <div [class]="classList">
    <div class="input-group">
    <span class="input-group-text border-0 bg-transparent">{{label}}</span>
    @if(type == 'text' || type == 'date') {
    <input
    [type]="type"
    [placeholder]="placeholder"
    [value]="value"
    (input)="onInputChange($event)"
    (blur)="onTouched()"
    class="form-control"
    [class.form-control-sm]="size == 'sm'"
    />
    }
    @if(type == 'select') {
    <select class="form-control" [class.form-control-sm]="size == 'sm'" (input)="onInputChange($event)"
    (blur)="onTouched()">
    <option value="">--Payer--</option>
    <option *ngFor="let o of selectOptions" [value]="o">{{o}}</option>
    </select>
    }
    </div>
    </div>
    }


    I have tried passing in the unique indexes, setting the formControlName inside the custom component, and setting unique ids. None of these solutions have worked.

    Continue reading...

Compartilhe esta Página