Angular2反应性表单控件验证取决于表单的外部属性

时间:2020-01-30 06:47:33

标签: angular forms validation angular2-directives

我在angular2中使用了一些验证器,例如相等的密码验证器。在这些情况下,两个控件的格式相同,我可以使用指令的validate方法访问这两个控件。

但是在我的情况下,Form有一个名称为Email的表单控件,仅当EmailFlag为true时才需要。 EmailFlag不是表单控件,将随时更新其值。我在验证程序的ngOnChanges中处理EmailFlag的更改值,并在验证程序的validate方法中处理Email的更改。

仅当调用validate方法时,我才能访问并将验证设置为表单控制。但是在更改标志时,我无法获得表单控件并对其进行验证。有什么办法可以控制标志更改并设置验证?

指令

@Directive({
  selector: '[requiredIfTrue]',
  providers: [{
    provide: NG_VALIDATORS,
    useExisting: RequiredIfTrueValidator,
    multi: true
  }]
})
export class RequiredIfTrueValidator implements OnChanges {
  _emailFlag: boolean;
  @Input('requiredIfTrue') public requiredIfTrue: boolean;

  validate(control: AbstractControl): { [key: string]: any } | null {
    if (this._emailFlag) {
      //set validation
    }
    else {
      //remove validation
    }
  }

  ngOnChanges(change: SimpleChanges) {
    if (change.requiredIfTrue) {
      this._emailFlag = change.requiredIfTrue.currentValue;
    }
  }
}

component.ts

EmailFlag = false;
//flag declared and changes value time by time

component.html

<input type="text" formControlName="Email" class="form-control" [requiredIfTrue]="EmailFlag" />

3 个答案:

答案 0 :(得分:1)

在自定义指令中注入NgControl,以在这样的自定义指令中获取FormControl求异实例

import { Directive, OnInit, Input } from '@angular/core';
import { NgControl, Validators } from '@angular/forms';
@Directive({
  selector: '[RequiredIfTrue]'
})
export class RequiredIfTrueDirective{
  @Input('RequiredIfTrue') set requited(value){
    console.log(value);
    if(value){
       this.control.control.setValidators(this.control.control.validator ? [this.control.control.validator, Validators.required] : Validators.required );
       this.control.control.updateValueAndValidity();
    }else{
            this.control.control.clearValidators();
            this.control.control.updateValueAndValidity();
    }
  };
  constructor(private control:NgControl) {

   }
}

Working Example

答案 1 :(得分:1)

如果您要使用一个验证器,该验证器取决于.ts中的变量,则可以使用bind(this)

emailFlag:boolean=true;
email=new FormControl("email",this.requiredIf().bind(this))

requiredIf()
  {
    return (control)=>{
      return this.emailFlag?!control.value?{required:true}:null:null
    }
  }

请注意,更改变量时,您需要进行updateValueAndValidity

click(){
   this.EmailFlag=!this.EmailFlag
   this.email.updateValueAndValidity()
}

请参阅stackblitz

注意:我使用this.requiredIf的方式来允许例如如果您有数组required=[true,false,false,true],则将“索引”传递给函数

那是

<form [formGroup]="form">
  <input formControlName="one">
  <small *ngIf="form.get('one').invalid">*</small>
  <button (click)="clickArray(0)">click</button>
  required:{{required[0]}}<br/>
    <input formControlName="two">
    <small *ngIf="form.get('two').invalid">*</small>
    <button (click)="clickArray(1)">click</button>
    required:{{required[1]}}<br/>
  <input formControlName="three">
  <small *ngIf="form.get('three').invalid">*</small>
  <button (click)="clickArray(2)">click</button>
  required:{{required[2]}}<br/>
</form>

然后您更改为

form = new FormGroup({
    one: new FormControl("", this.requiredIfArray(0).bind(this)),
    two: new FormControl("", this.requiredIfArray(1).bind(this)),
    three: new FormControl("", this.requiredIfArray(2).bind(this))
  });

requiredIfArray(index) {
  return control => {
    return this.required[index]? !control.value? { required: true }: null: null;
  };
}

答案 2 :(得分:0)

您可以使用updateValueAndValidity强制检查有效性。您也可以在formGroup上运行它。看到这里:https://netbasal.com/three-ways-to-dynamically-alter-your-form-validation-in-angular-e5fd15f1e946