想要添加带有角反应形式(嵌套形式)的自定义验证 [英] Want to Add a custom Validation with Angular Reactive Form (Nested Form)

查看:95
本文介绍了想要添加带有角反应形式(嵌套形式)的自定义验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆