typescript - Hur man väljer endast en kryssruta i ett dynamiskt formulär i Angular 8


Jag har ett dynamiskt formulär som genererar 8 olika kryssrutor beroende på API-svaret. Nu vill jag att användaren bara ska kunna välja en kryssruta åt gången. Om användaren vill välja en annan kryssruta måste han eller hon först avmarkera den valda kryssrutan. Vänligen se koden nedan.

<ng-container *ngIf="field.inputType==='group';else singleCase">
    <p class="font20" *ngIf="field.label">{{'label.' + field.name | translate}}</p>
    <div class="row purFin table-responsive pb-3 mb-2 mt-4">
      <div class="col-12">
        <ng-container [formArrayName]="field.name"
          *ngFor="let item of group.controls[field.name].controls; let i = index">
          <input type="checkbox" class="hidden" (click)="preventCheck($event)" (change)="onChange($event)" [formControlName]="i"
            [name]="field.name + i+1" [id]="field.name + i+1">
          <label class="btn-outline-secondary mr-3 mt-1 but" [for]="field.name + i+1">
            {{field.options[i].value}}
          </label>
        </ng-container>
        <div class="col-12">
          <span *ngIf="'sub_text.' + field.name | translate"
            class="font12">{{'sub_text.' + field.name | translate}}</span>
        </div>
      </div>
    </div>
    <div *ngIf="group.get(field.name).invalid && (group.get(field.name).dirty || group.get(field.name).touched)"
      class="error-msg">
      <ng-container *ngFor="let validation of field.validations">
        <div *ngIf="group.get(field.name).hasError(validation.name)">{{validation.message}}</div>
      </ng-container>
    </div>
  </ng-container>

Svar #1

Det kan göras på flera sätt, genom att reagera på ändrings-/klickhändelse och spara namnet på det markerade/klickade elementet. Betrakta nedan som ett exempel, kanske är det inte den mest eleganta lösningen, men du kan implementera logiken på många sätt faktiskt: [HTML]

export class YourComponentClass  {
  isChecked;
  isCheckedName;
  checkboxData = [1,2,3,4,5,6,7,8];
  onChange(e){       
    this.isChecked = !this.isChecked;
    this.isCheckedName = e.target.name;
  }
}
<div *ngFor="let name of checkboxData">
<input type="checkbox" [name]="name" (change)="onChange($event)" [disabled]="isChecked && (isCheckedName!=name)"> {{'Checkbox ' + name}}
 </div>

online: du kan kolla det på stackblitz

Och om du inte behöver mycket från $event är det bättre att bara skicka till komponenten de data du behöver, så du kan ändra till onChange($event.target.name) i HTML, och i TS-koden this.isCheckedName=e; därefter.

Lycka till ;)

Svar #2

Om du använder material/cdk i din app finns det en enkel att implementera lösning som involverar SelectionModel som fungerar bra med Reactive Forms/FormBuilder.

I din komponent deklarera:

selection = new SelectionModel<any>(false, []);

Sedan i din mall/html:

  <tr *ngFor="let item of formArray['controls']; let i = index;" [formGroupName]="i" class="tr-body-format">
        <td class="td-format">
             <mat-checkbox formControlName="selected" (change)="$event ? 
                  selection.toggle(i) : null" [checked]="selection.isSelected(i)">
             </mat-checkbox>
         </td>