Angular 个使用自定义验证和动态值的表单
Angular forms using custom validation and a dynamic value
我正在尝试创建一个自定义反应式表单验证,它允许我传递一组数据来检查字符串是否已经存在。我能够以一种方式进行,因此它将是表单级别的验证,但我无法让它在单个表单控件上工作。
表单级别验证
这将在整个表单上产生错误,而不仅仅是那个控件
this.myForm = this.fb.group({
name: ['', Validators.compose([
Validators.required,
]),
],
}, {
validator: (formGroup: FormGroup) => this.checkStringExists(
formGroup.controls.name,
this.arrayOfStrings,
),
});
允许我接受表单控件并根据传入的数组检查它的自定义验证。
checkStringExists(formInput: AbstractControl, names: string[]): { [s: string]: boolean } {
if (names && names.length && formInput && formInput.value) {
const isUnique = !names.find((name) => name === formInput);
if (isUnique) {
return { nameExists: true };
}
}
return null;
}
单独的控件验证(我想这样做的方式)
这只会在特定控件上产生错误
this.myForm = this.fb.group({
name: ['', Validators.compose([
Validators.required,
this.checkStringExists(this.arrayOfStrings),
]),
],
});
允许我仅将数组作为 Validators.compose[] 的一部分的自定义验证
这里
checkStringExists(names: string[]): ValidatorFn {
return (formInput: AbstractControl): ValidationErrors | null => {
if (names && names.length && formInput && formInput.value) {
const isUnique = !names.find((name) => name === formInput);
if (!isUnique) {
return { nameExists: true };
}
}
return null;
};
}
此订阅设置了 arrayOfStrings 的值。
mySubscription.subscribe((value: string[]) => {
this.arrayOfStrings = value;
})
我遇到的问题是 arrayOfStrings 可能会更新多次。
如果我使用第一种方式进行验证,则 arrayOfStrings 是最新的。如果我使用第二种方式进行验证,则 arrayOfStrings 是 null/initial 值。
我正试图让这个验证以第二种方式工作,这样我就可以显示基于单个控件的验证,而不是如果整个表单都有这个错误。有谁知道我如何传递这个值并使其保持最新?
我还在一个单独的帮助文件中提供了验证函数,以便在整个应用程序中重复使用。
更新
我的坏蛋!你可以传递一个数组,数组是一个不可变的值。所以如果你有
export function findArray(array){
return (control=>{
return array.indexOf(control.value)<0?{error:'not match'}:null
})
}
array=['one','two']
control=new FormControl(null,findArray(this.array))
你可以看到一个simple stackblitz
真的,验证器不能有“动态”参数。所以有些人喜欢
foolValidator(name:string)
{
return (control:AbstractControl)=>{
return control.value!=name?{error:'it's not the name'}:null
}
}
name="joe"
control=new FormControl(null,foolValidator(this.name))
只考虑'joe',不考虑变量名称“name”
您可以使用 bind(this)
,绑定更改“范围”,例如参见this link
foolValidator() //see that you not pass the argument
{
return (control:AbstractControl)=>{
//see that you use "this.name"
return control.value!=this.name?{error:'it's not the name'}:null
}
}
name="joe"
control=new FormControl(null,foolValidator().bind(this))
您的要求
您 post 似乎有以下愿望清单:
- 外部验证函数(用于在您的应用程序中重复使用)。
- 控制级别验证(并且,通过扩展,错误)而不是在表单级别。
- 用于再次验证您的字段的动态值列表。
解决方案
以下是从您上面的问题中复制的:
checkStringExists(formInput: AbstractControl, names: string[]): { [s: string]: boolean } {
if (names && names.length && formInput && formInput.value) {
const isUnique = !names.find((name) => name === formInput);
if (isUnique) {
return { nameExists: true };
}
}
return null;
}
与其在表单的验证器部分使用它,不如在字段级别使用它,如下所示:
// Contents could change later!
arrayOfStrings: string[] = [];
...
this.individualControlForm = this.fb.group({
name: ['', Validators.compose([
Validators.required,
(control: AbstractControl) => ValidationHelper.checkStringExists(
control, this.arrayOfStrings
)]),
],
});
因为我们使用箭头函数作为我们的验证函数,所以我们从函数定义的范围继承 this
("call, apply and bind" section, here 的释义)。这(嘿)意味着我们可以正常使用数组,每次调用验证函数时都使用最新值。
如果要减小此调用的大小,可以使用 .bind(this)
函数 。它会使事情更难阅读,但肯定会缩短创建表单的样板文件。选择你的毒药。
旁注
如果您确实需要使用整个表单验证(例如,如果您需要考虑多个字段来确定单个字段是否有效)但希望错误显示在您可以使用的字段上
formData.form.controls['email'].setErrors({'incorrect': true});
手动设置该特定字段的错误 ()。
我正在尝试创建一个自定义反应式表单验证,它允许我传递一组数据来检查字符串是否已经存在。我能够以一种方式进行,因此它将是表单级别的验证,但我无法让它在单个表单控件上工作。
表单级别验证
这将在整个表单上产生错误,而不仅仅是那个控件
this.myForm = this.fb.group({
name: ['', Validators.compose([
Validators.required,
]),
],
}, {
validator: (formGroup: FormGroup) => this.checkStringExists(
formGroup.controls.name,
this.arrayOfStrings,
),
});
允许我接受表单控件并根据传入的数组检查它的自定义验证。
checkStringExists(formInput: AbstractControl, names: string[]): { [s: string]: boolean } {
if (names && names.length && formInput && formInput.value) {
const isUnique = !names.find((name) => name === formInput);
if (isUnique) {
return { nameExists: true };
}
}
return null;
}
单独的控件验证(我想这样做的方式)
这只会在特定控件上产生错误
this.myForm = this.fb.group({
name: ['', Validators.compose([
Validators.required,
this.checkStringExists(this.arrayOfStrings),
]),
],
});
允许我仅将数组作为 Validators.compose[] 的一部分的自定义验证 这里
checkStringExists(names: string[]): ValidatorFn {
return (formInput: AbstractControl): ValidationErrors | null => {
if (names && names.length && formInput && formInput.value) {
const isUnique = !names.find((name) => name === formInput);
if (!isUnique) {
return { nameExists: true };
}
}
return null;
};
}
此订阅设置了 arrayOfStrings 的值。
mySubscription.subscribe((value: string[]) => {
this.arrayOfStrings = value;
})
我遇到的问题是 arrayOfStrings 可能会更新多次。 如果我使用第一种方式进行验证,则 arrayOfStrings 是最新的。如果我使用第二种方式进行验证,则 arrayOfStrings 是 null/initial 值。
我正试图让这个验证以第二种方式工作,这样我就可以显示基于单个控件的验证,而不是如果整个表单都有这个错误。有谁知道我如何传递这个值并使其保持最新?
我还在一个单独的帮助文件中提供了验证函数,以便在整个应用程序中重复使用。
更新
我的坏蛋!你可以传递一个数组,数组是一个不可变的值。所以如果你有
export function findArray(array){
return (control=>{
return array.indexOf(control.value)<0?{error:'not match'}:null
})
}
array=['one','two']
control=new FormControl(null,findArray(this.array))
你可以看到一个simple stackblitz
真的,验证器不能有“动态”参数。所以有些人喜欢
foolValidator(name:string)
{
return (control:AbstractControl)=>{
return control.value!=name?{error:'it's not the name'}:null
}
}
name="joe"
control=new FormControl(null,foolValidator(this.name))
只考虑'joe',不考虑变量名称“name”
您可以使用 bind(this)
,绑定更改“范围”,例如参见this link
foolValidator() //see that you not pass the argument
{
return (control:AbstractControl)=>{
//see that you use "this.name"
return control.value!=this.name?{error:'it's not the name'}:null
}
}
name="joe"
control=new FormControl(null,foolValidator().bind(this))
您的要求
您 post 似乎有以下愿望清单:
- 外部验证函数(用于在您的应用程序中重复使用)。
- 控制级别验证(并且,通过扩展,错误)而不是在表单级别。
- 用于再次验证您的字段的动态值列表。
解决方案
以下是从您上面的问题中复制的:
checkStringExists(formInput: AbstractControl, names: string[]): { [s: string]: boolean } {
if (names && names.length && formInput && formInput.value) {
const isUnique = !names.find((name) => name === formInput);
if (isUnique) {
return { nameExists: true };
}
}
return null;
}
与其在表单的验证器部分使用它,不如在字段级别使用它,如下所示:
// Contents could change later!
arrayOfStrings: string[] = [];
...
this.individualControlForm = this.fb.group({
name: ['', Validators.compose([
Validators.required,
(control: AbstractControl) => ValidationHelper.checkStringExists(
control, this.arrayOfStrings
)]),
],
});
因为我们使用箭头函数作为我们的验证函数,所以我们从函数定义的范围继承 this
("call, apply and bind" section, here 的释义)。这(嘿)意味着我们可以正常使用数组,每次调用验证函数时都使用最新值。
如果要减小此调用的大小,可以使用 .bind(this)
函数
旁注
如果您确实需要使用整个表单验证(例如,如果您需要考虑多个字段来确定单个字段是否有效)但希望错误显示在您可以使用的字段上
formData.form.controls['email'].setErrors({'incorrect': true});
手动设置该特定字段的错误 (