Angular 2 表单验证

Angular 2 Form Validation

我有这个表格使用 Angular 2:

<form [formGroup]="form">
    <div formArrayName="passageiros">
      <div *ngFor="let passageiro of form.get('passageiros')['controls']; let i=index">
          <div  [formGroupName]="i">
              <div class="row">
                  <div class="col-md-2">
                      <h3><strong   ngDefaultControl>{{ModPassageiros[i].NomeTipoPassageiro}} {{i + 1}}:</strong></h3>     
                  </div>   
                  <div class="col-md-2">
                      <mat-input-container style="width: 100%">
                          <input matInput [matDatepicker]="picker" placeholder="Data Nasc" [max]="maxDataNasc" formControlName="DataNascimento"  name="DataNascimento" [(ngModel)]="ModPassageiros[i].DataNascimento" (dateInput)="pegaIndice($event, i)" (dateChange)="pegaIndice($event, i)" required>
                          <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
                          <mat-datepicker #picker ></mat-datepicker>
                          <mat-error *ngIf="!form.controls.passageiros.controls[i].controls.DataNascimento.valid && !form.controls.passageiros.controls[i].controls.DataNascimento.pristine " >
                              Insira uma data de nascimento válida e de acordo com o tipo de pessoa (Adulto, criança ou bebê).
                          </mat-error>
                      </mat-input-container>  
                  </div>
              </div> 
          </div>
      </div>  
    </div>
</form>

我想根据乘客类型值验证出生日期。

这是类型脚本:

constructor(private fb:FormBuilder) { 
    this.form = this.fb.group({
          passageiros: this.fb.array([
            this.iniciaPassageiros(),
          ]),    
        }
      )
}

iniciaPassageiros() {
return this.fb.group({
  DataNascimento :[new Date(), Validators.compose([  
    Validators.required,
    (control) => this.validarDataNascPorTipo(control, this.indicePassageiros)
  ])]
});

}

public pegaIndice(e, i)
  { 
    this.indicePassageiros = i;
  }

这是自定义验证器函数:

    public validarDataNascPorTipo(control : AbstractControl, i)
  {
    let dias : number = this.util.calcularDias(control.value);
    if(this.ModPassageiros[i])
    {
      if(this.ModPassageiros[i].Tipo == 'ADT' && dias < 4015)
        return {"Data nascimento não é de " : true  

      if(this.Tipo == 'INF' && dias > 700)
        return { "Data nascimento não é de  ' + this.schemaJson.Metadados.Modelos.ModPassageiros[i].Tipo + '(abaixo de 23 meses)." : true }

      if(this.ModPassageiros[i].Tipo == 'CHD' && (dias > 4014 || dias < 700))
        return { "Data nascimento não é de  ' + this.schemaJson.Metadados.Modelos.ModPassageiros[i].Tipo + '(acima 23 meses e até de 11 anos)." : true};

      }  
    return null;
  }

我正在尝试传递实际索引以验证正确的控件,但 angular 在(更改)事件之前调用自定义验证函数。为此,验证没有预期的行为。我怎么解决这个问题?有没有办法通过控件传递表单数组的索引?或者,总是在更改事件之后调用验证函数?

由于您唯一需要的是索引,因此您可以使用父级获取它

iniciaPassageiros() {
   return this.fb.group({
     DataNascimento :[new Date(), [Validators.required,this.customValidator]
   });
}

  customValidator(control) {
    if (control) {
      let fbgroup = control.parent; //<--the FormGroup
      if (fbgroup) {
        let fbarray=fbgroup.parent;  //<--the FormArray
        let index=fbarray.controls.indexOf(fbgroup);
      }
    }

表单验证 Angular 将验证与组件相结合。

这导致围绕验证的业务逻辑分散在组件中的整个应用程序中。

很多时候最好创建一个基于 TypeScript 的可重复使用的验证服务

  • 这使得业务逻辑可以集中在一个地方。

  • 您可以通过对服务进行单元测试来对该业务逻辑进行单元测试。

演示 Angular 6 CLI 应用程序 向您展示了如何执行此操作。

https://github.com/VeritasSoftware/ts-validator-app-angular6

根据您的设计考虑,您可能会发现这很有用。