如何在angular中创建一个自定义验证器,在其他表单字段的基础上检查表单字段



组件的类型脚本是:

export class EtcAddAuthorityComponent implements OnInit {
addAuthorityForm: FormGroup;
authTypes: any[] = [];
loading = false;
numericRegex = /^[0-9]*$/;
alphabeticRegex = /^[a-zA-Z]*$/;
constructor(
private readonly dialogRef: MatDialogRef<EtcAddAuthorityComponent>,
private readonly fb: FormBuilder,
private readonly toastr: ToastrService,
private readonly ecmService: EcmService,
private readonly ecmToolChangeService: EcmToolChangeService,
private readonly cgpAlertDialogService: CgpAlertDialogService,
@Inject(MAT_DIALOG_DATA) public readonly selectedTool: any
) {
this.addAuthorityForm = this.fb.group({
authNumber: ['', [Validators.maxLength(20), Validators.pattern(this.alphabeticRegex)]],
authNumberN: ['', [Validators.required, Validators.maxLength(20), Validators.pattern(this.numericRegex)]],
authTypeName: ['', [Validators.required, Validators.maxLength(10)]],
authDescription: ['', [Validators.maxLength(500)]]
});
}

ngOnInit() {
this.loading = true;
this.ecmService.getAuthTypeCriteria()
.subscribe({
next: (res) => {
if (res) {
this.authTypes = res;
}
},
complete: () => this.loading = false
});
}
onCancelClick() {
this.dialogRef.close();
}
onAddClick() {
const authNFieldifAuthTypeName = this.authFieldCheck();
if (authNFieldifAuthTypeName === true) {
return;
}
else {
const body = {
...this.addAuthorityForm.value,
partChangeId: this.selectedTool.partChangeId,
toolChangeId: this.selectedTool.toolChangeId
};
this.loading = true;
this.ecmToolChangeService.addAuthority(body)
.subscribe({
next: (res) => {
this.cgpAlertDialogService.showAlertDialog({
title: 'Add Authority',
message: 'Authority was added successfully!',
alert: cgpAlertTypes.success,
closeLabel: 'OK'
}).afterClosed().subscribe(() => this.dialogRef.close({ reload: true }));
},
error: (err) => {
this.loading = false;
this.cgpAlertDialogService.showAlertDialog({
title: 'Add Authority',
message: 'Authority could not be added. Please try again!',
alert: cgpAlertTypes.danger,
closeLabel: 'OK'
});
},
complete: () => this.loading = false
});
}
}
authFieldCheck(): boolean {
const matched: boolean = (this.addAuthorityForm.controls.authTypeName.value === 'EWO') && (!this.addAuthorityForm.controls.authNumber.value);
if (matched) {
this.addAuthorityForm.controls.authTypeName.setErrors({
notFilled: true
});
}
else {
this.addAuthorityForm.controls.authTypeName.setErrors({ notMatched: false });
}
return matched;
}

}

html代码为:

<h1 mat-dialog-title>Add Authority</h1>
<div mat-dialog-content>
<form class="flex-dialog-container" [formGroup]="addAuthorityForm">
<mat-form-field>
<mat-label>Authority #(alpha)</mat-label>
<input matInput autocomplete="off" formControlName="authNumber" #authNumber>
<mat-error *ngIf="authNumber.value?.length > 20">Cannot exceed 20 characters.</mat-error>
</mat-form-field>
<mat-form-field>
<mat-label>Authority #(numeric)</mat-label>
<input matInput autocomplete="off" formControlName="authNumberN" #authNumberN>
<mat-error *ngIf="addAuthorityForm.controls.authNumberN.hasError('required')">Required</mat-error>
<mat-error *ngIf="authNumberN.value?.length > 20">Cannot exceed 20 characters.</mat-error>   
</mat-form-field>
<mat-form-field>
<mat-label>Authority Type</mat-label>
<mat-select formControlName="authTypeName">
<mat-option *ngFor="let at of authTypes" [value]="at.authTypeName">
{{at.authTypeName}}
</mat-option>
</mat-select>
<mat-error *ngIf="addAuthorityForm.controls.authTypeName.hasError('required')">Required</mat-error>
<mat-error *ngIf=" this.addAuthorityForm.controls.authTypeName.hasError('notFilled')">Authority #(alpha) required</mat-error>
</mat-form-field>
<mat-form-field>
<mat-label>Authority Description</mat-label>
<input matInput autocomplete="off" formControlName="authDescription" #authDescription>
<mat-error *ngIf="authDescription.value?.length > 500">Cannot exceed 500 characters.</mat-error>
</mat-form-field>
</form>
</div>
<div mat-dialog-actions class="mat-dialog-actions-end no-margin">
<button mat-raised-button mat-dialog-close cdkFocusInitial (click)="onCancelClick()"
(keypress.enter)="onCancelClick()">Cancel</button>
<button mat-raised-button color="primary" (click)="onAddClick()" (keypress.enter)="onAddClick()" [disabled]="addAuthorityForm.invalid">Add</button>
</div>

这是我的添加对话框:添加对话框

如何添加自定义验证,以便在"授权类型"下拉列表中选择"EWO"选项时,如果未输入"授权#(Alpha(",则会显示错误。但是,如果为"授权类型"下拉列表选择了"EWO"选项,则它不应显示任何错误。

您可以禁用;权威;如果您没有选择EWO,则Angular不会检查是否需要。要禁用/启用,您需要使用禁用和启用的方法

您可以使用指令禁用/启用控件,订阅valueChanges,或者,当您使用mat-select时,使用事件选择Change,如(*(:

<mat-select formControlName="authTypeName"
(selectionChange)="addAuthorityForm.get('authDescription')
[$event.value=='EWO'?'enable':'disable']()">
<mat-option *ngFor="let at of authTypes" [value]="at.authTypeName">
{{at.authTypeName}}
</mat-option>
</mat-select>

我做了一个简单的堆叠式

(*(不要忘记,在创建表单组时,创建启用或禁用的控件

更新如果我们不想禁用控件,我们确实需要创建一个自定义表单控件验证。

我们可以对FormControl、FormGroup或FormArray进行自定义表单控件验证。在这种情况下,我们选择make it而不是FromControl。但我们需要考虑的是,如果我们更改authTypeName,我们需要向Angular指示检查authDescription是否有效

<mat-select formControlName="authTypeName" 
(selectionChange)="form.get('authDescription').updateValueAndValidity()">
...
</mat-select>

好吧,我们的自定义表单验证。正如我们所拥有的";控制";,在控制中;我们有";形式";,所以它就像一样简单

requiredIf(requiredValue:string){
return (control:FormControl)=>{
const form=control.parent;
if (form)
{
//really we need decalre controlDescription, it's the
//same of "control"
const controlDescription=form.get('authDescription')
const controlTypeName=form.get('authTypeName')
if (controlTypeName && controlDescription && 
controlTypeName.value==requiredValue && !controlDescription.value)
return {required:true}
}
return null
}
}

我们可以写

form=new FormGroup({
authDescription:new FormControl(null,this.requiredIf('EWO')),
authTypeName:new FormControl('EWO')
})

在声明formGroup 时,请确保值"EWO"是固定的

新型堆叠式

我不知道你说";但是,如果为"授权类型"下拉列表选择了"EWO"选项,则它不应显示任何错误&";。我假设,如果没有为该场景输入"Authority#(Alpha(",它不应该显示任何错误。

可能有更好的解决方案,但以下是我在项目中使用的方法。您可以将这个块放在表单初始化之后,这样表单就可以访问以下身份验证类型和身份验证编号控件:

this.addAuthorityForm.get('authTypeName').valueChanges.subscribe((newValue) => {
const authNumber = this.addAuthorityForm.get('authNumber');
// I don't know the exact structure of the authTypeName so you can debug and change the condition if needed
if (newValue === 'EWO') { 
authNumber.setValidators([Validators.required, Validators.maxLength(20), Validators.pattern(this.alphabeticRegex)]);
} else {
authNumber.setValidators([Validators.maxLength(20), Validators.pattern(this.alphabeticRegex)]);
}
authNumber.updateValueAndValidity();
})

基本上,当身份验证类型更改时,通过添加所需的验证器来为身份验证号重新分配验证器。我使用Validators.required是因为它是开箱即用的,但如果你想让它更自定义,你可以有这样的东西:

...
authNumber.setValidators([(c: FormControl) => {
return c.value ? null : {required: {valid: false}};
}, Validators.maxLength(20), Validators.pattern(this.alphabeticRegex)]);
...

updateValueAndValidity方法是在用户切换身份验证类型时重新验证字段。

最新更新