Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
206 views
in Technique[技术] by (71.8m points)

typescript - Angular 2 conditional Validators.required?

How should I go about conditionally requiring a form field? I made a custom validator, but the conditional variables that I pass to the custom validator are static and remain their initial values. What should my custom validator look like to get updated conditional values? Perhaps there is a way to do this with Validators.required instead of a custom validator?

private foo: boolean = false;
private bar: boolean = true;

constructor(private _fb: FormBuilder) {
    function conditionalRequired(...conditions: boolean[]) {
      return (control: Control): { [s: string]: boolean } => {
        let required: boolean = true;
        for (var i = 0; i < conditions.length; i++) {
          if (conditions[i] === false) {
            required = false;
          }
        }
        if (required && !control.value) {
          return { required: true }
        }
      }
    }
    this.applyForm = _fb.group({
          'firstName': ['', Validators.compose([
            conditionalRequired(this.foo, !this.bar)
          ])],
          ...
    });
}

Update (May 17, 2016)

It's been a long time since posting this, but I'd like to reference the .include() and .exclude() methods available on the ControlGroup class for anyone out there who is trying to create this functionality. (docs) While there are probably use cases for a conditional Validator like above, I've found the inclusion and exclusion of controls, control groups, and control arrays to be a great way to handle this. Just set the required validator on the control you'd like and include/exclude it as you please. Hope this helps someone!

question from:https://stackoverflow.com/questions/36118721/angular-2-conditional-validators-required

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Following your comment I can see a potential problem. Since you provide conditions as primitive types to the function that creates the validators function, the values when calling the first one will be used. Even if they change after, the new values won't be taken into account.

To archive that you need to use an object for conditions as described below:

private foo: boolean = false;
private bar: boolean = true;

private conditions: any = {
  condition1: foo,
  condition2: !bar
};

constructor(private _fb: FormBuilder) {
    function conditionalRequired(conditions: any) {
      return (control: Control): { [s: string]: boolean } => {
        let required: boolean = true;
        for (var elt in conditions) {
          var condition = conditions[elt];
          if (conditions === false) {
            required = false;
          }
        }
        if (required && !control.value) {
          return { required: true };
        }
      }
    }
    this.applyForm = _fb.group({
          'firstName': ['', Validators.compose([
            conditionalRequired(conditions)
          ])],
          ...
    });
}

This way the conditions parameter can be used / updated by reference. To update your conditions, you need to do the following:

updateConditions() {
  this.conditions.condition1 = true;
  this.conditions.condition2 = true;
}

Here is a plunkr: https://plnkr.co/edit/bnX7p0?p=preview.

Edit

To run the validator when updating the conditions, you need to explicitly call the updateValueAndValidity method of the control. In this case, the valid attribute of both control and form will be updated accordingly:

updateConditions() {
  this.conditions.condition1 = true;
  this.conditions.condition2 = true;
  this.applyForm.controls.firstName.updateValueAndValidity();
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...