我遇到多重验证无法正常工作的问题。 例如 validate1 方法检查输入是否为空,validation2 方法检查 name1 和 name2 值是否相等。例如 name1= Angular 且 name2 为空。形式有效是显示为真,但实际逻辑为假
validate1() - 设置表单有效 false,validate2() - 设置表单有效 true,根据逻辑形式无效
注:
有些场景我只会使用 validate1(),有些场景我会使用 仅 validate2(),某些场景我将同时使用两者
validate1()、validate2() 是示例逻辑。我还需要方法3 通过方法2的验证器
导入{ 成分, 指示, 关于变化, 初始化时, 转发参考, 输入, 注射器, 查看孩子, NG形式 来自“@Angular/Core”; 从 '@angular/platform-browser' 导入 { bootstrapApplication } ; 进口 { NG_VALIDATORS, 验证器Fn, 抽象控制, 验证错误, NG控制, 反应式表单模块, 表单模块, 表单控件, 来自“@角度/形式”; 从 '@angular/common' 导入 { CommonModule };
@Directive({
selector: '[appdirective1]',
standalone: true,
})
export class directiveName implements OnChanges, OnInit {
@Input() varName1 = '';
@Input() varName2 = '';
@Input() callBack1!: (control: AbstractControl) => ValidationErrors | null;
@Input() callBack2!: (control: AbstractControl) => ValidationErrors | null;
constructor(private _injector: Injector) {}
validate1(): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
//logic here it is sample logic
return (control.value !== '' || control.value !== null || control.value !== undefined)
? {
invalidName: control.value,
}
: null;
};
}
validate2(): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
const obj1 = this.callBack1(control);
return obj1;
};
}
validate3(): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
const obj1 = this.callBack2(control);
return obj1;
};
}
ngOnInit() {
this.conditionallyAddValidators();
}
conditionallyAddValidators() {
const control = this._injector.get(NgControl);
control?.control?.addValidators(this.validate1());
if (this.varName1 !== '' && this.varName1 !== undefined) {
control?.control?.addValidators(this.validate2());
}
if (this.varName2 !== '' && this.varName2 !== undefined) {
control?.control?.addValidators(this.validate3());
}
control?.control?.updateValueAndValidity();
}
ngOnChanges() {
this.conditionallyAddValidators();
}
}
@Component({
selector: 'app-root',
standalone: true,
imports: [directiveName, ReactiveFormsModule, CommonModule, FormsModule],
template: `
<form #f="ngForm">
<input appdirective1 name="name1" [callBack1]="method2" [formControl]="control" [(ngModel)]="name1"/>
<br/>
<br/>
<hr/>
<input appdirective1 name="name2"" [callBack2]="method1" [(ngModel)]="name2" />
<br/>
{{f.valid | json}}
<br/>
<hr/>
</form>
`,
})
export class App {
name1 = 'Angular';
name2="";
success = 'required';
@ViewChild('f', {static:false}) form:NgForm;
method1(control: AbstractControl) {
const value = control?.value;
return this.form.form.get('name2').value !==this.form.form.get('name1').value
?null
: {
minLength: true,
};
}
method2(control: AbstractControl) {
const value = control?.value;
return value?.length >= 10
? {
maxLength: true,
}
: null;
}
方法3(控制:AbstractControl){ //自己的逻辑 返回值?.length >= 10 ? { 最大长度:真, } : 无效的; } }
bootstrapApplication(App);
在
validate1
中:您有一个始终为 true 的条件,因为您错误地使用了 or
运算符:return (control.value !== '' || control.value !== null || control.value !== undefined)
您正在尝试将
callBack1
和 callBack2
连接到 validate2
和 validate3
等验证器,但这样做背后的逻辑令人困惑,因为您单独提供 callBack1/callBack2
作为输入。
对于何时以及如何调用方法
method1
和 method2
存在一些困惑。
根据需要创建可重用的自定义验证器。 使用复合验证器有效地组合多个验证条件。 动态管理特定领域的验证者而不干扰其他领域。
重构指令代码
import {
Directive,
OnChanges,
OnInit,
Input,
Injector,
ChangeDetectorRef,
} from '@angular/core';
import {
NG_VALIDATORS,
ValidatorFn,
AbstractControl,
ValidationErrors,
NgControl,
} from '@angular/forms';
@Directive({
selector: '[appdirective1]',
providers: [
{
provide: NG_VALIDATORS,
useExisting: DirectiveName,
multi: true,
},
],
})
export class DirectiveName implements OnChanges, OnInit {
@Input() varName1 = '';
@Input() varName2 = '';
@Input() callBack1!: (control: AbstractControl) => ValidationErrors | null;
@Input() callBack2!: (control: AbstractControl) => ValidationErrors | null;
private control!: NgControl;
constructor(private _injector: Injector, private cdr: ChangeDetectorRef) {}
ngOnInit() {
this.control = this._injector.get(NgControl);
this.conditionallyAddValidators();
}
ngOnChanges() {
this.conditionallyAddValidators();
this.control?.control?.updateValueAndValidity(); // Trigger validation when inputs change
}
validate1(): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
// Ensure the input is not empty
return control.value == null || control.value.trim() === ''
? {
invalidName: 'Field is required',
}
: null;
};
}
validate2(): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
const result = this.callBack1 ? this.callBack1(control) : null;
return result;
};
}
validate3(): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
const result = this.callBack2 ? this.callBack2(control) : null;
return result;
};
}
conditionallyAddValidators() {
const control = this.control?.control;
if (!control) return;
// Clear existing validators
control.clearValidators();
// Always add validate1
control.addValidators(this.validate1());
// Add validate2 and validate3 when conditions or callbacks are provided
if (this.varName1 !== undefined && this.varName1 !== '') {
control.addValidators(this.validate2());
}
if (this.varName2 !== undefined && this.varName2 !== '') {
control.addValidators(this.validate3());
}
control.updateValueAndValidity(); // Make sure validator updates are reflected
}
}
和下面的组件代码
import {
Component,
ViewChild,
} from '@angular/core';
import { FormControl, NgForm, ValidationErrors } from '@angular/forms';
@Component({
selector: 'app-root',
standalone: true,
imports: [],
template: `
<form #f="ngForm">
<!-- Field 1 -->
<input
appdirective1
name="name1"
[callBack1]="method2"
[(ngModel)]="name1"
varName1="used"
/>
<br />
<!-- Field 2 -->
<input
appdirective1
name="name2"
[callBack2]="method1"
[(ngModel)]="name2"
varName2="used"
/>
<br />
<hr />
<!-- Valid State -->
<div>Form Valid: {{ f.valid | json }}</div>
<!-- Errors for Field 1 -->
<div>
Name1 Errors: {{ f.form.controls['name1']?.errors | json }}
</div>
<!-- Errors for Field 2 -->
<div>
Name2 Errors: {{ f.form.controls['name2']?.errors | json }}
</div>
</form>
`,
})
export class App {
name1 = 'Angular';
name2 = '';
@ViewChild('f', { static: false }) form!: NgForm;
method1(control: AbstractControl): ValidationErrors | null {
const name1Value = this.form?.form.get('name1')?.value;
return control.value !== name1Value
? null
: {
valuesMatch: true, // error when name1 and name2 are equal
};
}
method2(control: AbstractControl): ValidationErrors | null {
return control.value && control.value.length >= 10
? {
maxLength: true,
}
: null;
}
}