In Angular, how to add Validator to FormControl after control is created?
Asked Answered
O

8

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.

Openwork answered 5/8, 2016 at 20:34 Comment(0)
R
199

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)]);
Reredos answered 5/8, 2016 at 20:47 Comment(11)
ha...sometimes you look at something so long it is best to just step away. THANK YOU!!Openwork
This really solved the problem that I was trying to fix for a long time. Thanks a ton for sharing!Helping
Is there a way to remove validationSoot
Cheers. If you have css in the field use .patchValue() after so the the styling refresh.Emilemile
dude it is like a hack, consider a scenario where there are 50 fields or more generated from xsd sent from server which has basic validators like max length or min length and then there are dynamic mandatory fields based on user then i can't get existing validtors or push to existing validators.Corliss
any way to do this without overriding the old ones? or any way to append the new ones?Pungent
@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.Accommodation
Note that this will clear all existing validators that may have been set during form initialization.Antichrist
I had to also call .updateValueAndValidity() on the form control after setting the new validators.Printer
Explains how to wipe and reset validators, not add validatorsCobb
addValidators() was added in v12.2.0 github.com/angular/angular/blob/master/…Huldahuldah
B
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.

Bissell answered 11/12, 2017 at 11:21 Comment(8)
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!Dextrorotation
@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.Hectorhecuba
I'm on Angular 6 and couldn't make it work without the updateValueAndValidity. Thanks @Bissell !Wurster
On Angular 7 and it also wouldn't work for me without the last update line.Evenfall
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()`.Nightcap
In my case, it worked only when I removed updateValueAndValidity().Pesthouse
First I put all this in AfterViewInit, which did not work. Then I put the logic in OnInit, then it worked.Accustomed
Explains how to wipe and reset validators, not add validatorsCobb
D
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.

Donative answered 13/11, 2018 at 8:32 Comment(3)
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 VoidAccommodation
I agree with my predecessor. The question was how to add new validator to control form, not how to replace it.Endoenzyme
I did control.setValidators(control.validator ? [ control.validator, Validators.email ] : Validators.email); to get around strict null checksProtean
B
8

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.

Briefcase answered 28/7, 2021 at 8:8 Comment(0)
B
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 ]);
Brigettebrigg answered 19/12, 2019 at 16:50 Comment(1)
This is very good solution for Angular 12 prior version but this.clearValidators(); will remove the existing validators and add new passed validator.Jaan
J
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.

Jos answered 18/7, 2019 at 13:45 Comment(2)
You'd think control.setValidators(control.validator ? [ control.validator, Validators.email ] : Validators.email); would work.Protean
See @Eduard Void 's answer https://mcmap.net/q/158155/-in-angular-how-to-add-validator-to-formcontrol-after-control-is-createdProtean
S
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

Smoke answered 18/3, 2021 at 14:5 Comment(0)
W
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

Worshipful answered 30/11, 2022 at 9:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.