typescript - Hur man validerar att minst en kryssruta är markerad i Angular
Jag har en lista med angular-rutor och behöver kontrollera om minst en är markerad.
Kryssruteobjekten är dynamiska (de kommer från en tjänst) så det är inte en statisk lista. En gång kan det finnas 3 element och en annan gång kan det finnas fler än 50 osv.
Mallen ser ut så här:
<tr *ngFor="let recipient of recipients">
<td class="disable edit">
<div>
<span class = "textbluesmall"><input type="checkbox" [checked]="true" value="{{recipient?.participantId }}" name="participant" />{{recipient?.lastName }} ,{{recipient?.firstName }}</span>
</div>
</td>
<td class="disable edit">
<div>
<span>{{recipient?.email }}</span>
</div>
</td>
</tr>
Och jag försöker lösa det på det här sättet men det fungerar inte
.TS FIL:
var checkboxs=document.getElementsByName('participant');
var okay=false;
for(var i=0,l=checkboxs.length;i<l;i++)
{
if(checkboxs[i].checked){
okay=true;
break;
}
}
if(okay){
return true;
}
else{
return false;
}
}
How can I do this the easiest way?
Svar #1
din konstruktor
constructor(private formBuilder: FormBuilder) {
this.form = this.formBuilder.group({
recipients: new FormArray([], minSelectedCheckboxes(1))
});
lägg till den här funktionen
function minSelectedCheckboxes(min = 1) {
const validator: ValidatorFn = (formArray: AbstractControl) => {
if (formArray instanceof FormArray) {
const totalSelected = formArray.controls
.map((control) => control.value)
.reduce((prev, next) => (next ? prev + next : prev), 0);
return totalSelected >= min ? null : { required: true };
}
throw new Error('formArray is not an instance of FormArray');
};
return validator;
}
Svar #2
Eftersom kryssrutorna måste skapas dynamiskt, behöver du använda Reactive Forms i Angular.
Reaktiva formulär består huvudsakligen av tre typer av klasser, nämligen,
FormGroupsFormArrayFormControl
För att kunna skapa kryssrutor dynamiskt skulle du behöva börja med att importera FormsModule och ReactiveFormsModule i din module.ts-fil, och lägga till dem i imports-arrayen i din @NgModule-dekoration.
På samma sätt importerar du FormBuilder och FormGroup i din component.ts-fil. Använd sedan FormBuilder-tjänsten för att skapa din FormGroup som kommer att deklareras i din mall.
export class AppComponent {
form: FormGroup;
arrayOfRecepients = [];
constructor(private formBuilder: FormBuilder) {
this.form = this.formBuilder.group({
recipients: new FormArray([])
});
}
}
I din mallfil, koppla formulärelementet med [formGroup]="form"
<form [formGroup]="form">
<!-- Template code for checkboxes -->
</form>
Iterera genom din array av mottagare för att lägga till nya instanser av FormControl till FormArray. Sätt kontrollen till false, så att kryssrutorna markeras som avmarkerade. På detta sätt kommer form-arrayen att betrakta varje enskild kryssruta som en del av sin samling av kontroller.
this.arrayOfRecepients.forEach(() => this.recipientsFormArray.push(new FormControl(false)));
I din templatfil, iterera över din array av mottagare med hjälp av *ngFor-direktivet. Definiera formArrayName som recipients eftersom det krävs för att informera formulär-API:n.
<form [formGroup]="form" (ngSubmit)="submit()">
<label formArrayName="recipients" *ngFor="let recepient of recipientFormArray.controls; let i = index">
<input type="checkbox" [formControlName]="i">
{{arrayOfRecipients[i].name}}
</label>
</form>
För att validera kryssrutorna behöver du skicka in din valideringsfunktion som en andra parameter till FormArray.
Valideringsfunktionen bör vara sådan att den tar ditt formArray och antalet minst markerade kryssrutor som krävs, som indata. Den bör hämta värdena från kontrollen, räkna antalet kontrollvärden som är sanna, och sedan jämföra antalet med minimum.
TLDR;
För din referens, vänligen hitta länken till en fungerande demo här
