如何解决如何使一个自定义验证器以角度检查基于另一个表单域的表单域?
该组件的打字稿是:
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.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>
这是我的添加对话框: The Add dialog box
如何添加自定义验证,以便在“权限类型”下拉列表中选择“ EWO”选项时,如果未输入“ Authority#(Alpha)”,则会显示错误。但是,如果在“权限类型”下拉列表中选择了“ EWO”选项,则应该不会显示任何错误。
解决方法
如果您不选择EWO,则可以禁用“ Authority”,因此Angular不会检查是否需要。要禁用/启用,您需要使用方法disable and enable
您可以使用directive to disable/enable控件,订阅valueChanges或在使用mat-select时使用事件selectionChange之类的(*):
<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>
我做了一个simple stackblitz
(*)不要忘记,在创建表单组时,创建启用或禁用的控件
更新,如果我们不想禁用该控件,则确实需要创建一个自定义的Form控件Validation。
我们可以对FormControl,FormGroup或FormArray进行自定义窗体控件验证。在这种情况下,我们选择通过FromControl进行设置。但是我们需要考虑到,如果我们更改了authTypeName
,我们需要向Angular指示以检查authDescription
是否有效
<mat-select formControlName="authTypeName"
(selectionChange)="form.get('authDescription').updateValueAndValidity()">
...
</mat-select>
好吧,我们的自定义表单验证。由于我们拥有“控件”,因此在control.parent中我们拥有“表格”,因此就像
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();
})
基本上,此操作是在auth类型更改时通过添加所需的验证器来为auth号重新分配验证器。我使用Validators.required
是因为它是开箱即用的,但是如果您想使其更自定义,则可以使用以下内容:
...
authNumber.setValidators([(c: FormControl) => {
return c.value ? null : {required: {valid: false}};
},Validators.pattern(this.alphabeticRegex)]);
...
updateValueAndValidity
方法是在用户切换身份验证类型时重新验证该字段。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。