想要添加带有角反应形式(嵌套形式)的自定义验证 [英] Want to Add a custom Validation with Angular Reactive Form (Nested Form)
问题描述
我正在使用Angular Reactive表单,并且有如下数据:
I'm using Angular Reactive form and I have a data like below:
detail = {
customerNo: '1231234123412',
nameKanji: 'test0',
nameKana: 'かな',
gender: '0',
birthday: '2019-02-02',
telNo: '79-0999-1111',
addressZip: '120-0813',
address: 'takenotsuka0',
email: 'slack@test.com',
point: '1231230',
family: [
{ name: 'テスト0', relationship: "wife" },
{ name: 'テスト1', relationship: "brother" }
]
};
我已经如下定义了我的formGroup
And I have defined my formGroup like below
this.detailForm = this.fb.group(
{
global: [null],
customerNo: [
null,
[Validators.required, StringValidator.equalLength(13)]
],
nameKanji: [null, [Validators.required, Validators.maxLength(60)]],
nameKana: [null, [Validators.required, Validators.maxLength(60)]],
gender: ['1', [Validators.required]],
birthday: [null, [Validators.required]],
addressZip: [null, []],
telNo: [null, [Validators.required, StringValidator.equalLength(13)]],
address: [null],
email: [null, [Validators.email, Validators.maxLength(100)]],
point: [null, [Validators.required]],
family: this.fb.array([])
},
{ updateOn: 'blur' }
);
public addFamilyGroup() {
return this.fb.group({
name: [null, [Validators.required]],
relationship: [null, [Validators.required]]
});
}
get familyArray(): FormArray {
return <FormArray>this.detailForm.get('family');
}
如您所见,family是数据结构中的嵌套数组,现在,如果我已经具有family.wife值,我想为其添加自定义验证.
As you can see family is a nested array in datastructure and Now I want to add a custom validation to it if I have already have a family.wife value.
检查下面的图像.如果我已经选择了妻子,下次再次选择妻子,则需要显示错误的验证消息.非常感谢.
check the image below. If I have already select a wife and the next time if I select the wife again I need to show the validation message of error. Thanks a lot.
推荐答案
您需要在创建表单数组的customFormArray总是一样的(我喜欢将自定义表单错误作为函数放置在组件本身中
It's allways the same to create a customFormArray of a Form Array (I like put the custom form error as function in the component itselft
allDifferent()
{
return (formArray:FormArray)=>{
//we create an array only with the "relationShip"
const value=formArray.value?formArray.value.map(x=>x.relationship):null
//(value.filter(...) create an array with the repeat values
//so, we check the length to return null or an object
return value &&
(value.filter((item, index) => item && value.indexOf(item) != index)).length>0?
{error:"values repeat"}:null
}
}
当您创建表单时
family: this.fb.array([],this.allDifferent())
更新,如果我们需要重复索引,我们可以创建一个自定义formError,该错误返回"error".具有重复索引的数组,请记住,我们选择了要返回的内容
Update if we want the repeat index, we can create a custom formError that return in "error" an array with the repeat index, remember that we choose what we want return
allDifferentIndex()
{
return (formArray:FormArray)=>{
//we create an array of objects [{relationship:..,index:..},{relationship:..,index:...}..]
const value=formArray.value?formArray.value
.map((x,index)=>({relationship:x.relationship,index:index})):null
if (value)
{
//we filter the array only with the values repeats
const repeatValues=(value.filter((item, index) => item.relationship &&
value.findIndex(f=>f.relationship==item.relationship) != index))
//if the array length>0 return an object {error:value}
// the value is an array of numbers, we use map to return only the "index"
return repeatValues.length?{error:repeatValues.map(x=>x.index)}:null
}
}
}
我们可以使用类似
<div formArrayName="family">
<div *ngFor="let group of familyArray.controls;let i=index" [formGroupName]="i">
<input formControlName="relationship">
<span *ngIf="familyArray.errors?.error && familyArray.errors.error.indexOf(i)>=0">
*
</span>
</div>
</div>
并使用
family: this.fb.array([],this.allDifferentIndex())
更新2 ,我们可以创建更通用的customError,只是一个函数
Update 2 we can create a customError more general, just a function
export function allDifferentIndex(property:string)
{
return (formArray:FormArray)=>{
const value=formArray.value?formArray.value.map((x,index)=>({field:x[property],index:index})):null
if (value)
{
const repeatValues=(value.filter((item, index) => item.field && value.findIndex(f=>f.field==item.field) != index))
return repeatValues.length?{error:repeatValues.map(x=>x.index)}:null
}
}
}
并用作
family: this.fb.array([],allDifferentIndex('relationship'))
使用输入的简单 stackblitz -我使用了最后一个方法,一个外部函数,但是我在代码中留给了其他人
A simple stackblitz using inputs -I use the last aproach, a external function, but I left in the code the others one
这篇关于想要添加带有角反应形式(嵌套形式)的自定义验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!