9

Can I conditionally implement validation in Angular 2 reactive form. I have this reactive form with 3 formControl fields one is a selection and the other two are input text for first name and last name. I want to conditionally implements validation for firstname and lastname based on the selection of the first field which is 'validateBy'. If the user selects 'byFirstName' only firstName should be validated. If the user selects 'byLastName' only lastName should be validated. If the user selects 'byBoth' both firstName and lastName should be validated. I created a plunker for this. Only validation byBoth works.

ngOnInit() {
this.myForm = this._fb.group({
  validateBy: ['byFirstName'],
  firstName:  ['', isFirstNameValid(() => (this.validateBy === 'byFirstName' || this.validateBy === 'byBoth'),
                     Validators.required)],
  lastName: ['', isLastNameValid(() => (this.validateBy === 'byLastName' || this.validateBy === 'byBoth'),
                     Validators.required)],
}); 

https://plnkr.co/edit/X0zOGf?p=preview

1
  • you can if you write a custom directive validation Commented Apr 19, 2017 at 9:36

3 Answers 3

12

The problem is that your code evaluates the expression just once - when the FormGroup is created. You need to make it dynamic by creating your custom validator that will evaluate the expression every time it gets called:

this.personForm= this.fb.group({
  firstName: ['', Validators.required];
  lastName:  [
    '', 
    conditionalValidator(
      (() => this.isValidationForLastName === true),
      Validators.required
    )
  ]
});

function conditionalValidator(condition: (() => boolean), validator: ValidatorFn): ValidatorFn {
  return (control: AbstractControl): {[key: string]: any} => {
    if (! condition()) {
      return null;
    }
    return validator(control);
  }
}
Sign up to request clarification or add additional context in comments.

8 Comments

Halasa I tried your code. now it doesn't validate :(
Have you tried to debug it? Is the validator called? Do you have some error messages in the browser console?
just few changes what if my condition will be based on string not boolean. I updated my question.
With a string variable, you change just the condition function: (() => this.isValidationForLastName === 'validateIt'). If you implemented it and it doesn't work, please add your code to the question or create a plunker (or similar) example.
Halasa I updated my question and I already created a plunker similar to my problem. Can you check my plunker.
|
11

Another way of doing it would be something like this. Seems to work on plunker

  ngOnInit() {
    this.myForm = this._fb.group({
      validateBy: ['byFirstName'],
      firstName:  [''],
      lastName: [''],
    });

    this.myForm.get('validateBy').valueChanges.subscribe(
        (validateBy : string) => {
          if (validateBy === 'byFirstName' || validateBy === 'byBoth') {
            this.myForm.get('firstName').setValidators([Validators.required]);
            this.myForm.get('firstName').updateValueAndValidity();
          }
          if (validateBy === 'byLastName' || validateBy == 'byBoth') {
            this.myForm.get('lastName').setValidators([Validators.required]);
            this.myForm.get('lastName').updateValueAndValidity();
          }

        };
      )
  }

Comments

0

I made a library just for this.

Your solution might look something like:

constructor(private cv: ConditionallyValidateService, private fb: FormBuilder) {}

ngOnInit() {
    this.myForm = this._fb.group({
        validateBy: ['byFirstName'],
        firstName:  [''],
        lastName: [''],
     });

    cv.validate(this.myForm, 'firstName')
        .using(Validators.required)
        .when('validateBy')
        .is('byFirstName')

    cv.validate(this.myForm, 'lastName')
        .using(Validators.required)
        .when('validateBy')
        .is('byLastName')

    cv.validate(this.myForm, 'firstName', 'lastName')
        .using(Validators.required)
        .when('validateBy')
        .is('byBoth')

}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.