146

We have a component that has a dynamically built form. The code to add a control with validators might look like this:

var c = new FormControl('', Validators.required);

But let's say that I want to add 2nd Validator later. How can we accomplish this? We cannot find any documentation on this online. I did find though in the form controls there is setValidators

this.form.controls["firstName"].setValidators 

but it is not clear how to add a new or custom validator.

9 Answers 9

201

You simply pass the FormControl an array of validators.

Here's an example showing how you can add validators to an existing FormControl:

this.form.controls["firstName"].setValidators([Validators.minLength(1), Validators.maxLength(30)]);

Note, this will reset any existing validators you added when you created the FormControl.

Angular 12 update

Since Angular 12, if you want to add new validators to the form without removing the existing validators, you can use addValidator:

this.form.controls["firstName"].addValidators([Validators.minLength(1), Validators.maxLength(30)]);
Sign up to request clarification or add additional context in comments.

11 Comments

ha...sometimes you look at something so long it is best to just step away. THANK YOU!!
Is there a way to remove validation
any way to do this without overriding the old ones? or any way to append the new ones?
@danday74, check out Eduard Void's answer at the bottom of this question. Should be accepted answer imo. He explains how to do what you need to know, which I also needed to know how to do.
I had to also call .updateValueAndValidity() on the form control after setting the new validators.
|
142

To add onto what @Delosdos has posted.

Set a validator for a control in the FormGroup: this.myForm.controls['controlName'].setValidators([Validators.required])

Remove the validator from the control in the FormGroup: this.myForm.controls['controlName'].clearValidators()

Update the FormGroup once you have run either of the above lines. this.myForm.controls['controlName'].updateValueAndValidity()

This is an amazing way to programmatically set your form validation.

8 Comments

For me it worked without the last line, I'm pretty sure new versions of Angular update the form validity by themselves now. But thanks for telling us about the updateValueAndValidity method, might come handy one day!
@NinoFiliu updateValueAndValidity is still used to perform the validation, and isn't handled any differently in newer versions of Angular. What happens is setValidators updates the validators, but doesn't run a validation check, and then you use updateValueAndValidity to perform the validation. You must be setting the validators at a point where change detection handles it for you, but you'll find using updateValueAndValidity on the group or control depending what validator you just set crucial - github.com/angular/angular/issues/19622#issuecomment-341547884.
I'm on Angular 6 and couldn't make it work without the updateValueAndValidity. Thanks @shammelburg !
On Angular 7 and it also wouldn't work for me without the last update line.
Yes. It is working without updateValueAndValidity(), but in some cases, it does not. if you added updateValueAndValidity() after setValidators() It will immediately affect the changes related to control. So it is better to add updateValueAndValidity()`.
|
121

If you are using reactiveFormModule and have formGroup defined like this:

public exampleForm = new FormGroup({
        name: new FormControl('Test name', [Validators.required, Validators.minLength(3)]),
        email: new FormControl('[email protected]', [Validators.required, Validators.maxLength(50)]),
        age: new FormControl(45, [Validators.min(18), Validators.max(65)])
});

than you are able to add a new validator (and keep old ones) to FormControl with this approach:

this.exampleForm.get('age').setValidators([
        Validators.pattern('^[0-9]*$'),
        this.exampleForm.get('age').validator
]);
this.exampleForm.get('email').setValidators([
        Validators.email,
        this.exampleForm.get('email').validator
]);

FormControl.validator returns a compose validator containing all previously defined validators.

3 Comments

Imo this should be the accepted answer. It demonstrates how to add validators like OP requested, but also shows you how to retain previously set validators; which was the first thing I googled how to do after I read the accepted answer, because I didn't want to overwrite some validators I already had, but still needed to programatically add additional ones. Thank you for this answer @Eduard Void
I agree with my predecessor. The question was how to add new validator to control form, not how to replace it.
I did control.setValidators(control.validator ? [ control.validator, Validators.email ] : Validators.email); to get around strict null checks
9

If you need to remove some existing validation on the added form control then call below function on the control

this.form.controls["name"].clearValidators();

After that you need to call below function to update the form controls and it will be effective immediately on the form controls.

this.form.controls['name'].updateValueAndValidity();

If you need to add some validation on the already added form control then call the below function on the control

this.signupForm.controls['name'].setValidators([Validators.required]);

After that call updateValueAndValidity() function immediately, so it can be reflected instantly.

Comments

7

In addition to Eduard Void answer here's the addValidators method:

declare module '@angular/forms' {
  interface FormControl {
    addValidators(validators: ValidatorFn[]): void;
  }
}

FormControl.prototype.addValidators = function(this: FormControl, validators: ValidatorFn[]) {
  if (!validators || !validators.length) {
    return;
  }

  const old_validator = this.validator;

  this.clearValidators();
  this.setValidators( old_validator ? [ old_validator , ...validators ] : validators );
};

Using it you can set validators dynamically:

some_form_control.addValidators([ first_validator, second_validator ]);
some_form_control.addValidators([ third_validator ]);

1 Comment

This is very good solution for Angular 12 prior version but this.clearValidators(); will remove the existing validators and add new passed validator.
5

I think the selected answer is not correct, as the original question is "how to add a new validator after create the formControl".

As far as I know, that's not possible. The only thing you can do, is create the array of validators dynamicaly.

But what we miss is to have a function addValidator() to not override the validators already added to the formControl. If anybody has an answer for that requirement, would be nice to be posted here.

2 Comments

You'd think control.setValidators(control.validator ? [ control.validator, Validators.email ] : Validators.email); would work.
See @Eduard Void 's answer stackoverflow.com/a/53276815/6656422
0

A simple solution would be to first get all the validators in the form control and assign a new validatorFn to it when needed code will go like this.

//get existing validators and assign a new validator

const formControl = this.form.controls["firstName"];

 const validators: ValidatorFn[] = !!formControl.validator ?
  [formControl.validator, Validators.required] :
  [Validators.required];

formControl.setValidators(validators);

formControl.validtor holds the existing validators (not asyncValidators) we check if it's not null using ternary and add to it ( here we add the required validator to it), otherwise, we just assign our new validator

Comments

0

Updating validators based on other Form Control's values.

First setting the form:

  form: FormGroup = new FormGroup({
    firstName: new FormControl<string>(null),
    lastName: new FormControl<string>(null),
  });

then on init:

  ngOnInit(): void {
    this.form.get('firstName').valueChanges.subscribe((value) => {
      if (value) {
        this.form.get('lastName').setValidators(Validators.nullValidator);
      } else {
        this.form.get('lastName').setValidators(Validators.required);
      }
      this.form.get('lastName').updateValueAndValidity({ emitEvent: false });
    });
    this.form.get('lastName').valueChanges.subscribe((value) => {
      if (value) {
        this.form.get('firstName').setValidators(Validators.nullValidator);
      } else {
        this.form.get('firstName').setValidators(Validators.required);
      }
      this.form.get('firstName').updateValueAndValidity({ emitEvent: false });
    });
  }

It's important to add { emitEvent: false } so you don't get the Maximum call stack size exceeded error

Comments

0

The setValidators method should work with a FormControl even after the control is created in Angular.

Ensure updateValueAndValidity is called: After setting the validators, always call updateValueAndValidity to recalculate the value and validation status of the control.

this.form.controls["firstName"].setValidators([Validators.required]);
this.form.controls["firstName"].updateValueAndValidity(); // Ensure the validators are applied

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.