如何验证 angular2 中的 FormArray 长度

Posted

技术标签:

【中文标题】如何验证 angular2 中的 FormArray 长度【英文标题】:How to Validate FormArray length in angular2 【发布时间】:2017-06-30 07:14:48 【问题描述】:

我有一个 angular2 中的数据驱动形式,如下所示

this.formBuilder.group(
  'name': ['',Validators.required],
  'description': ['', Validators.required],
  'places': this.formBuilder.array([], Validators.minlength(1)) 
)

我想向place formArray 添加验证,所以我要添加minlength 验证,但 minlength 验证不适用于 formArray。

formArray 的其他验证是什么,因此表单必须仅在 places 数组包含至少一个位置时才有效。

【问题讨论】:

从头开始应该可以工作github.com/angular/angular/commit/… 您可能也对此github.com/angular/angular/commit/… 感兴趣,无论如何这应该可以确保您拥有最新版本 【参考方案1】:

Validators.required 为您施展魔法:

// using required 

this.formGroup = this.formBuilder.group(
    taskTreeId: [Common.UID()],
    executionProgrammedTime: ["", [Validators.required]],
    description: [""],
    tasks: this.formBuilder.array([], Validators.required)
);  

// using custom validation

export const minLengthArray = (min: number) => 
  return (c: AbstractControl): [key: string]: any => 
    if (c.value.length >= min)
      return null;

    return  MinLengthArray: true;
  


 this.formGroup = this.formBuilder.group(
        taskTreeId: [Common.UID()],
        executionProgrammedTime: ["", [Validators.required]],
        description: [""],
        tasks: this.formBuilder.array([], minLengthArray(2))
    );
<button type="button" class="btn btn-success btn-rounded" 
    [disabled]="!formGroup.valid">SAVE</button>

【讨论】:

你好,我实现了这个,但它不起作用。即使我勾选了一个复选框,我也无法将 form.valid 更改为“true”。还有什么需要补充的吗? 如果您想以其他方式限制数组的长度,也可以使用 Validators.maxLength 或 minLength。 这是正确的答案,Validators.required 调用名为isEmptyInputValue 的函数来检查值是null 还是length === 0。见Angular Source file @NetanelDraiman 非常感谢您的洞察力!我想更加确定 required 表单数组验证是如何在 Angular 中完成的。【参考方案2】:

将此自定义验证器添加到您的验证服务中:

minLengthArray(min: number) 
    return (c: AbstractControl): [key: string]: any => 
        if (c.value.length >= min)
            return null;

        return  'minLengthArray': valid: false ;
    

然后在创建表单时执行以下操作:

this.formBuilder.group(
  'name': ['',Validators.required],
  'description': ['', Validators.required],
  'places': this.formBuilder.array([], this.validationService.minLengthArray(1)) 
);

您可以通过检查FormArray.hasError('minLengthArray') 来检查FormArray 的错误

【讨论】:

嘿,它确实有效:) - 但是我如何让它“冒泡”到表单中 - 防止提交(它不适合我)? 你在使用引导程序吗?这是一个示例: 必须上传文件才能创建订单 我的 ts 中有这个:this.form = this._fb.group( files: this._fb.array([], this ._vs.minLengthArray(1)) ); 好的,可以,但我希望有一种方法可以让这个自定义验证器自动“影响”表单(无效)有效性,所以我不必明确检查 formArrays 有效性- 就像内置的验证器一样。现在看来,它确实做到了 - 不知道为什么昨天没有:D【参考方案3】:

因为你使用了错误的验证器函数名:minlength -> minLength

演示代码:

import  Component, OnInit  from '@angular/core';
import  FormBuilder, FormGroup, FormArray, Validators  from '@angular/forms';

@Component(
  selector: 'app-root',
  template: `
    <form novalidate [formGroup]="tpForm" (ngSubmit)="onSubmit()">
      <div><input type="text" formControlName="name"></div>
      <div><textarea formControlName="description"></textarea></div>
      <div formArrayName="places">
        <button type="button" (click)="addPlace()">+</button>
        <div *ngFor="let place of places.controls; let i = index">
          <div>
              <span>Places i + 1</span>
              <button type="button" *ngIf="places.controls.length > 0" 
                  (click)="removePlace(i)">
                  x
              </button>
          </div>
          <input type="text" [formControlName]="i">
        </div>
      </div>
      <button type="submit">Submit</button>
    </form>

    <p>Status:  tpForm.valid </p>
  `,
  styles: [
    `


    `
  ]
)
export class AppComponent implements OnInit 
  tpForm: FormGroup;

  constructor(private fb: FormBuilder) 

  ngOnInit() 
    this.tpForm = this.fb.group(
      'name': ['',Validators.required],
      'description': ['', Validators.required],
      'places': this.fb.array([
        this.fb.control('')
      ], Validators.minLength(1))
    )
  

  get places(): FormArray 
    return this.tpForm.get('places') as FormArray;
  

  onSubmit() 

  

  addPlace() 
    this.places.push(this.fb.control(''));
  

  removePlace(index) 
    this.places.removeAt(index);
  


Plunker:https://plnkr.co/edit/cfi7nN?p=preview

【讨论】:

【参考方案4】:

做到这一点的好方法是:

创建一个Array.validator.ts 并将所有自定义验证放在那里,例如minLengthmaxLength

import  ValidatorFn, AbstractControl, FormArray  from '@angular/forms';

// Array Validators
export class ArrayValidators 

    // max length
    public static maxLength(max: number): ValidatorFn | any 
        return (control: AbstractControl[]) => 
            if (!(control instanceof FormArray)) return;
            return control.length > max ?  maxLength: true  : null;
        
    

    // min length
    public static minLength(min: number): ValidatorFn | any 
        return (control: AbstractControl[]) => 
            if (!(control instanceof FormArray)) return;
            return control.length < min ?  minLength: true  : null;
        
    

然后只需导入该文件并在任何您想要的地方使用验证:

import  ArrayValidators  from './array.validator'; // Import it

'hobbies':new FormArray([],ArrayValidators.minLength(2)) // Use it

WORKING DEMO


注意:

你也可以直接使用这个包ng-validator(参考来自这个包),但是如果 你只需要所需的数组验证,你可以像上面那样做。

【讨论】:

这真的很有帮助,谢谢。我试图使用标准Validators.minLength(1) 无济于事。不知何故,我假设在内部,SOME_OBJECT.lengthSOME_STRING.length 将能够使用相同的验证器......【参考方案5】:

如果您尝试向 formarray 添加验证,请尝试这可能会对您有所帮助,

this.formBuilder.group(
  'name': ['',Validators.required],
  'description': ['', Validators.required],
  'places': this.formBuilder.array(this.initPlaces()) 
)

initPlaces()        
        return this._fb.group(
            places: ['',[Validators.minLength(1)]]           
        );
  

这个initPlaces 将根据要求简单地返回带有验证的formGroup。

【讨论】:

【参考方案6】:

有一个模板

<div formArrayName="items">
    <div *ngFor="[...] let i = index" [formGroupName]="i">

    [...]

    </div>
</div>

您可以简单地在按钮中使用它:

[disabled]="!myForm.get('items.1')"

【讨论】:

【参考方案7】:
this.profileForm = this.fb.group(
      firstName: [''],
      lastName: [''],
      hobbies: this.fb.array([this.fb.control('')], Validators.minLength(2))
);

只需使用Validators.minLength(length)。 https://angular.io/api/forms/Validators#minLength

【讨论】:

以上是关于如何验证 angular2 中的 FormArray 长度的主要内容,如果未能解决你的问题,请参考以下文章

FormArray验证中的Angular2 FormGroup

如何根据 Angular 2 中的自定义验证规则显示错误消息?

如何正确验证 HTML 输入中的数字范围? (角度 2)

如何在 Angular2 中触发表单验证器

如何使用 Reactive Forms (Angular2 RC3) 进行异步验证?

Angular2如何对自定义验证器指令进行单元测试?