Angular 模板驱动表单的自定义交叉字段验证器
Angular custom cross fields validator for Template Driven Form
在模板驱动形式中,我必须检查是否至少选中了一个复选框。我创建了一个自定义验证器。
HTML形式:
<div class="form-group">
<div class="form-check con-errori">
<label for="conErrori" class="form-check-label">
<input type="checkbox" name="conErrori" #conErrori="ngModel" [(ngModel)]="conErroriInput"
id="conErrori" class="form-check-input" data-either-validator="form-check-input" data-either-group-container-selector=".form-group">Con errori
</label>
</div>
<div class="form-check senza-errori">
<label for="senzaErrori" class="form-check-label">
<input type="checkbox" name="senzaErrori" #senzaErrori="ngModel" [(ngModel)]="senzaErroriInput"
id="senzaErrori" class="form-check-input" data-either-validator="form-check-input" data-either-group-container-selector=".form-group">Senza errori
</label>
</div>
<div *ngIf="!conErrori.valid && (conErrori.dirty ||conErrori.touched)" class="error">
<div *ngIf="conErrori.errors.ev">
Selezionare almeno una voce
</div>
</div>
<div *ngIf="!senzaErrori.valid && (senzaErrori.dirty ||senzaErrori.touched)" class="error">
<div *ngIf="senzaErrori.errors.ev">
Selezionare almeno una voce
</div>
</div>
</div>
validator.ts:
import { Directive, Input, ElementRef, Renderer2 } from '@angular/core';
import { FormControl, NG_VALIDATORS, Validator } from '@angular/forms';
@Directive({
selector: '[data-either-validator]',
providers: [
{ provide: NG_VALIDATORS, useExisting: EitherValidatorDirective, multi: true }
]
})
export class EitherValidatorDirective implements Validator{
/*classGroup contains the class to identify all the checkboxes to validate*/
@Input("data-either-validator") classGroup:string;
/*groupContainerSelector contains the selector to identify the element that
contains the checkboxex, so I can validate only those checkboxes*/
@Input("data-either-group-container-selector") groupContainerSelector:string;
constructor(private elRef: ElementRef, private renderer: Renderer2) { }
validate(formControlValue: FormControl) {
/*with the following code I find all the checkboxes with a specific class inside a specific html element
and I check if at least one is selected*/
let groupContainer = this.elRef.nativeElement.closest(this.groupContainerSelector);
let formControlOfSameGroup = groupContainer.querySelectorAll("." + this.classGroup)
let validationResult:boolean = false;
formControlOfSameGroup.forEach(element => {
if(element.checked){
validationResult = true;
}
});
if(!validationResult){
return { 'ev': true}
}
else{
return null;
}
}
}
我的问题是很难处理错误消息,因为我可能有 10-20 个复选框,我应该处理尽可能多的复选框
<div *ngIf="!senzaErrori.valid && (senzaErrori.dirty ||senzaErrori.touched)" class="error">
<div *ngIf="senzaErrori.errors.ev">
Selezionare almeno una voce
</div>
</div>
作为我的复选框。
处理这个问题的正确方法是什么(我有一个模板驱动的表单而不是反应式表单)?
我的方法是否是处理跨字段验证(以模板驱动形式)的好方法?
谢谢
解决方案在 guidelines 上,我错过了。
@Directive({
selector: '[appIdentityRevealed]',
providers: [{ provide: NG_VALIDATORS, useExisting: IdentityRevealedValidatorDirective,
multi: true }]
})
export class IdentityRevealedValidatorDirective implements Validator {
validate(control: AbstractControl): ValidationErrors {
/*this way you can retrieve the value of the fields you have to validate*/
const name = control.get('name');
const alterEgo = control.get('alterEgo');
if(error){
return { 'errorCode': true}
}
else{
return null;
}
}
}
在跨字段验证期间,验证器应应用于表单而不是字段。
<form #heroForm="ngForm" appIdentityRevealed>
<div *ngIf="heroForm.errors?.errorCode && (heroForm.touched || heroForm.dirty)" class="cross-validation-error-message alert alert-danger">
Name cannot match alter ego.
</div>
在模板驱动形式中,我必须检查是否至少选中了一个复选框。我创建了一个自定义验证器。
HTML形式:
<div class="form-group">
<div class="form-check con-errori">
<label for="conErrori" class="form-check-label">
<input type="checkbox" name="conErrori" #conErrori="ngModel" [(ngModel)]="conErroriInput"
id="conErrori" class="form-check-input" data-either-validator="form-check-input" data-either-group-container-selector=".form-group">Con errori
</label>
</div>
<div class="form-check senza-errori">
<label for="senzaErrori" class="form-check-label">
<input type="checkbox" name="senzaErrori" #senzaErrori="ngModel" [(ngModel)]="senzaErroriInput"
id="senzaErrori" class="form-check-input" data-either-validator="form-check-input" data-either-group-container-selector=".form-group">Senza errori
</label>
</div>
<div *ngIf="!conErrori.valid && (conErrori.dirty ||conErrori.touched)" class="error">
<div *ngIf="conErrori.errors.ev">
Selezionare almeno una voce
</div>
</div>
<div *ngIf="!senzaErrori.valid && (senzaErrori.dirty ||senzaErrori.touched)" class="error">
<div *ngIf="senzaErrori.errors.ev">
Selezionare almeno una voce
</div>
</div>
</div>
validator.ts:
import { Directive, Input, ElementRef, Renderer2 } from '@angular/core';
import { FormControl, NG_VALIDATORS, Validator } from '@angular/forms';
@Directive({
selector: '[data-either-validator]',
providers: [
{ provide: NG_VALIDATORS, useExisting: EitherValidatorDirective, multi: true }
]
})
export class EitherValidatorDirective implements Validator{
/*classGroup contains the class to identify all the checkboxes to validate*/
@Input("data-either-validator") classGroup:string;
/*groupContainerSelector contains the selector to identify the element that
contains the checkboxex, so I can validate only those checkboxes*/
@Input("data-either-group-container-selector") groupContainerSelector:string;
constructor(private elRef: ElementRef, private renderer: Renderer2) { }
validate(formControlValue: FormControl) {
/*with the following code I find all the checkboxes with a specific class inside a specific html element
and I check if at least one is selected*/
let groupContainer = this.elRef.nativeElement.closest(this.groupContainerSelector);
let formControlOfSameGroup = groupContainer.querySelectorAll("." + this.classGroup)
let validationResult:boolean = false;
formControlOfSameGroup.forEach(element => {
if(element.checked){
validationResult = true;
}
});
if(!validationResult){
return { 'ev': true}
}
else{
return null;
}
}
}
我的问题是很难处理错误消息,因为我可能有 10-20 个复选框,我应该处理尽可能多的复选框
<div *ngIf="!senzaErrori.valid && (senzaErrori.dirty ||senzaErrori.touched)" class="error">
<div *ngIf="senzaErrori.errors.ev">
Selezionare almeno una voce
</div>
</div>
作为我的复选框。
处理这个问题的正确方法是什么(我有一个模板驱动的表单而不是反应式表单)?
我的方法是否是处理跨字段验证(以模板驱动形式)的好方法?
谢谢
解决方案在 guidelines 上,我错过了。
@Directive({
selector: '[appIdentityRevealed]',
providers: [{ provide: NG_VALIDATORS, useExisting: IdentityRevealedValidatorDirective,
multi: true }]
})
export class IdentityRevealedValidatorDirective implements Validator {
validate(control: AbstractControl): ValidationErrors {
/*this way you can retrieve the value of the fields you have to validate*/
const name = control.get('name');
const alterEgo = control.get('alterEgo');
if(error){
return { 'errorCode': true}
}
else{
return null;
}
}
}
在跨字段验证期间,验证器应应用于表单而不是字段。
<form #heroForm="ngForm" appIdentityRevealed>
<div *ngIf="heroForm.errors?.errorCode && (heroForm.touched || heroForm.dirty)" class="cross-validation-error-message alert alert-danger">
Name cannot match alter ego.
</div>