Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 4 remove required validator conditionally

In Angular 4 app I have a form model like this:

this.form = this._fb.group({
    title: ['', [Validators.required, Validators.minLength(3), Validators.maxLength(50)]],
    description: ['', [Validators.required, Validators.minLength(3)]]
});

Now what I want is to remove dynamically only the required validator from the control validators array. Something like this:

saveDraft() {
    this.form.controls['title'].removeValidator('required'); //Just a fake implementation for demonstration
}

This question is not the duplicate of the mentioned question. My case is different I just want to remove the required validator unknowingly the other ones.

like image 802
Ali Shahzad Avatar asked Sep 29 '17 11:09

Ali Shahzad


People also ask

How do I remove validators required?

Either first use “clearValidators()” to remove all validators and then use “setValidators()” to set needed validation. Or directly use “setValidators()” with the needed validators only (without the validator you don't want to have).

How do you set a validator dynamically?

We can add Validators dynamically using the SetValidators or SetAsyncValidators. This method is available to FormControl, FormGroup & FormArray. There are many use cases where it is required to add/remove validators dynamically to a FormControl or FormGroup.

How do I remove a validator from reactive form?

We can either use clearValidators() to remove all validators and then use setValidators() to set needed validation, or we can directly use setValidators() with the needed validators only (without the validator you don't want to have).

What is updateValueAndValidity?

updateValueAndValidity allows you to modify the value of one or more form controls and the flag allows you to specify if you want this to emit the value to valueChanges subscribers. Follow this answer to receive notifications.


8 Answers

if you want to add validation try this one.

saveDraft() {
   this.form.get('title').setValidators([Validators.required, Validators.minLength(3)]);
   this.form.get('title').updateValueAndValidity();
}

if you want to remove validators try this one.

saveDraft() {
 this.form.get('title').clearValidators();
 this.form.get('title').updateValueAndValidity();
}
like image 62
Singam Avatar answered Oct 31 '22 19:10

Singam


I don't like clearing and setting validators, as I have to repeat all static validators (patterns, min, max, etc.) just to have a dynamic "required" validator.

I use a conditional validator:

export function conditionalValidator(condFn: (control: AbstractControl) => boolean,
validators: ValidatorFn | ValidatorFn[]): ValidatorFn {
  return (control) => {
    if (!condFn(control)) {
      return null;
    }

    if (!Array.isArray(validators)) {
      return validators(control);
    }

    return validators.map(v => v(control)).reduce((errors, result) =>
      result === null ? errors :
        (Object.assign(errors || {}, result))
    );
  };
}

I can then mix a static validator with a dynamic "required" condition:

this.fb.group({name: ['', [Validators.minLength(4),
                 conditionalValidator(this.isClientProj, Validators.required)]]}

Where isClientProj() is the condition function (closure)

like image 35
Alex R Avatar answered Oct 31 '22 20:10

Alex R


we can use setValidators to remove validation.

setValidators(newValidator: ValidatorFn | ValidatorFn[]): void

setValidators() - setValidators programmatically adds the sync validators. This method will remove all the previously added sync or async validators.

this.form.get('title').setValidators(null); 
this.form.get('title').setErrors(null); 
like image 24
Akash Kumar Verma Avatar answered Oct 31 '22 21:10

Akash Kumar Verma


You can use: AbstractControl.removeValidators(validator: ValidatorFn)

Not sure if it is possible in angular 4, but definately in Angular 12 and higher.

It needs however, a reference to the exact same function. Just giving it Validators.required does not work. You need to create a unique reference to it:

requiredValidator = Validators.required;
   
this.form = this._fb.group({
    title: ['', [this.requiredValidator, Validators.minLength(3), Validators.maxLength(50)]],
    description: ['', [this.requiredValidator, Validators.minLength(3)]]
}); 

saveDraft() {
    this.title.removeValidators(this.requiredValidator); 
}

get title(): AbstractControl {
    return this.form.get('title');
}
like image 41
Tombalabomba Avatar answered Oct 31 '22 19:10

Tombalabomba


To Add Validators:

this.form = this._fb.group({
    title: ['', [Validators.required, Validators.minLength(3), Validators.maxLength(50)]],
    description: ['', [Validators.required, Validators.minLength(3)]]
});

or

this.form.get('title').setValidators([Validators.required,Validators.minLength(3), Validators.maxLength(50)]);

To Remove the 'Required' validator only, you can reset the validators.

saveDraft() {
     this.form.get('title').setValidators([Validators.minLength(3), Validators.maxLength(50)]);
     this.form.get('title').updateValueAndValidity();
}

updateValueAndValidity determines how the control propagates changes and emits events when the value and validators are changed

like image 45
Dilushika Weerawardhana Avatar answered Oct 31 '22 20:10

Dilushika Weerawardhana


Unfortunately Angular doesn't have a removeValidator capability at this point in time. All you can do is re-set the validators without the one you want to remove, so you need to know which validators you want to keep rather than which one you want to remove. so this:

this.form.get('title').setValidators([Validators.minLength(3), Validators.maxLength(50)]);

Is the closest you have to a remove function. You can't access the current validators on a formcontrol either to try and write your own remove function. The best you could do is write your own form control validation manager class that can keep track of the validators on a given control and manage them for you.

like image 36
bryan60 Avatar answered Oct 31 '22 19:10

bryan60


I had the same problem with saving entry as draft and prepared the following solution:

@Component({
    // ...
})
export class FormComponent{
    form: FormGroup;

    constructor(private fb: FormBuilder){
        this.form = this.fb.group({
            name: ['', Validators.required, Validators.maxLength(20)],
            description: ['', Validators.required, Validators.maxLength(200)],
            address: this.fb.group({
                line1: ['', Validators.required, Validators.maxLength(100)],
                line2: ['', Validators.maxLength(100)]
            })
        });
    }    

    validateDraft(formElement: FormGroup | FormArray | FormControl): boolean {
        let result = true;

        Object.keys(formElement.controls).forEach(field => {
            const control = formElement.get(field);

            if(control instanceof FormControl) {
                control.markAsTouched({ onlySelf: true });

                if(control.errors && control.errors['required']) {
                    control.markAsUntouched({ onlySelf: true });
                }
                else if(control.invalid) {
                    result = false;
                }
            } else if (control instanceof FormArray) {
                if (!this.validateDraft(control)) {
                    result = false;
                } 
            }else if (control instanceof FormGroup) {
                if (!this.validateDraft(control)) {
                    result = false;
                }   
            }
        });
    }

    saveDraft(){
        if(this.validateDraft(this.form)){
            //save draft - ignore required errors
        }
    }

    save(){
        if(this.form.valid){
            //save
        }
    }
}
like image 36
kalinowski Avatar answered Oct 31 '22 20:10

kalinowski


this.fromName.get("formControlName").setValidators([Validators.required]);//setting validation
this.fromName.get("formControlName").setErrors({'required':true});//error message
this.fromName.updateValueAndValidity();//update validation


this.fromName.get("formControlName").clearValidators([Validators.required]);//clear validation
this.fromName.get("formControlName").setErrors(null);//updating error message
this.fromName.updateValueAndValidity();//update validation
like image 39
Sanjeet Kumar Avatar answered Oct 31 '22 19:10

Sanjeet Kumar