11

I am trying to create a conditional required validation on a specific field.I try doing this by return Validators.required back in my function, but this doesn't seem to work. How do I go about doing this? Here's my code:

private _ansat: AbstractControl = new FormControl('', Validators.required);
private _helbred: AbstractControl = new FormControl('', Validators.compose([this.useValidateIfRadio(this._ansat, 0, Validators.required)]) );


constructor(private _fb: FormBuilder) {
    this.myForm = this._fb.group({
            ansat: this._ansat,
            helbred: this._helbred
        });
}

useValidateIfRadio (c: AbstractControl, n: number, v) {
        return function (control) {
            return new Promise(resolve => {
             // this.msg = ansatControl.value;
             console.log(v);
                if (c.value === n) {

                    resolve(v);
                }
                else {
                  resolve(null);

                }
            });
        };
    };

Any help is greatly appreciated.

3
  • Did you solve this? I have added a answer, and are curious if you solved it the same way (or even in a better way) Commented Feb 6, 2017 at 9:12
  • 1
    I solved a similar issue with a reusable custom validator as shown here: Conditional Required Commented Feb 6, 2017 at 9:16
  • ah, that looks genius! I will test your solution then! Commented Feb 6, 2017 at 9:25

3 Answers 3

32

I had a similar problem but couldn't find a answer. Since nobody has answered this yet I'll provide an example of how I solved my problem, and how you can solve your issue using the same solution.

Example: (Phone number is required only if email is not set)

export class UserComponent implements OnInit {

userForm: FormGroup;

constructor(private fb: FormBuilder) {}

ngOnInit() {

    //Create my userForm and and add initial validators
    this.userForm = this.fb.group({
        username: [null, [Validators.required]],
        name: [null, [Validators.required]],
        email: [],
        phoneNumber: [null, [Validators.required, Validators.minLength(4)],
    });

    //Listen to email value and update validators of phoneNumber accordingly
    this.userForm.get('email').valueChanges.subscribe(data => this.onEmailValueChanged(data));
}


onEmailValueChanged(value: any){
    let phoneNumberControl = this.userForm.get('phoneNumber');

    // Using setValidators to add and remove validators. No better support for adding and removing validators to controller atm.
    // See issue: https://github.com/angular/angular/issues/10567
    if(!value){
        phoneNumberControl.setValidators([Validators.required, Validators.minLength(4)]);
    }else {
        phoneNumberControl.setValidators([Validators.minLength(4)]);
    }

    phoneNumberControl.updateValueAndValidity(); //Need to call this to trigger a update
}

}

So in your case you should add a changeListener to "_ansat" equal to my email listener, and then add required to "_helbred" accordingly.

Sign up to request clarification or add additional context in comments.

Comments

5

Just add validator for the field:

if(some_logic) {
 this.your_form.get('field_name').setValidators([Validators.required]);
}

Comments

1

These answers got me most of the way there, but I found out a pretty big gotcha… in some cases, setValidators only adds to the existing array of validators and does not work well to clear them. In some cases, like when ngOnInit loads twice in a row, the conditions could be first negative and then positive for a passed-in value you're depending on. In such a case, you will set it to required, then later attempt to clear it, but the UI will still behave like it expects it. To fix this, consider the following...

const myControl = this.your_form.get('field_name');
if(some_logic) {
     myControl.clearAsyncValidators();
     myControl.clearValidators();
     myControl.updateValueAndValidity({onlySelf:true});
} else {
     myControl.setValidators([Validators.required, Validators.other…]);
}

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.