23

I´m trying to set a form control status to valid

this.currencyForm.controls['currencyMaxSell'].setErrors({smallerThan: true})

now I want delete this error.

3
  • 5
    You can run validation - this.currencyForm.controls['currencyMaxSell'].updateValueAndValidity() Commented Apr 17, 2017 at 5:10
  • 4
    Try setError(null) Commented Apr 17, 2017 at 6:55
  • stackoverflow.com/a/68526302/5456789 use markAsUntouched Commented Jul 26, 2021 at 7:58

15 Answers 15

26

Other solutions seem to not work. It looks like angular thinks the control is invalid as long as the errors property is not null.

As long as you want to remove just a single error and leave others there's no way to do it but manually. This function will remove only one error specified in the argument and leave others. It will also make sure that if you remove the last error the control will become valid.

// call it in validator function if control is valid
removeError(this.currencyForm.controls['currencyMaxSell'], 'smallerThan');

// this function removes single error
function removeError(control: AbstractControl, error: string) {
  const err = control.errors; // get control errors
  if (err) {
    delete err[error]; // delete your own error
    if (!Object.keys(err).length) { // if no errors left
      control.setErrors(null); // set control errors to null making it VALID
    } else {
      control.setErrors(err); // controls got other errors so set them back
    }
  }
}

// this function adds a single error
function addError(control: AbstractControl, error: string) {
  let errorToSet = {};
  errorToSet[error] = true;
  control.setErrors({...control.errors, ...errorToSet});
}
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, it works but I think control.setErrors(err); is not necessary because it set the same object that is already setted.
Worked perfectly in Angular 7. Thank you for sharing this much-needed function.
7

To remove only one form control error when performing manual validation, do the following:

this.myFormGroup.get('myControl').setErrors({'myCustomError':null})

This will only update the value for the specified error, and will not erase any previous validation you may have done, as opposed to setErrors(null), which nullifies the whole errors object for the control.

3 Comments

I just saw now that this is from April, 2017. Hope it still helps though.
if I need to nullifies all errors of all controls in a form like myFormGroup.controls.setErrors(null) is there any chance of it ?
For me it leave FormControl as invalid.
6

Just set the value in the error object to null:

this.currencyForm.controls['currencyMaxSell'].setErrors({smallerThan: null})

Or if you want to remove all the validation from the control use setErrors(null) as suggested in the comments.

2 Comments

This is wrong! If you do that, still currencyForm.invalid is true
This is not correct ... discussion here github.com/angular/angular/issues/21564
6

You can create custom validators for formControl and formGroup and inside the validator, return a ValidatorFn. You shouldn't use setErrors method.

For more info about custom validators for FormGroup, I suggest this article.

Here's my code:

registerationForm = this.formBuilder.group({
  username: ['', [Validators.required, Validators.email]],
  passwords: this.formBuilder.group(
    {
      password: ['', Validators.required],
      confirmPassword: ['', Validators.required]
    },
    {
      validator: matchPassword
    }
  ),
  policyAgreement: ['', Validators.required]
});

// Outside my component:
const matchPassword = (group: FormGroup) => {
  const password = group.get('password').value;
  const confirmPassword = group.get('confirmPassword').value;
  return password != confirmPassword ? { matchPassword: true } : null;
};

2 Comments

setErrors is useful when you want to set errors returned from the server after you have submitted the form, I'm not sure the custom validators can be used in those cases.
the argument to matchPassword above... should it be of type FormGroup? It is a group level validation, no?
3

Using Angular 7, none of the solutions presented here worked for me.

I had to handle my error manually in my custom validator that works with multiple form fields.

The example below checks if the difference between two form fields is large enough. The form fields in question have multiple other validators as well (lte, gte), so clearing all errors with setError(null) was out of the question, and trying to remove my specific error with setError({minDifference: null}) always left the formControl in an invalid state.

minDifference(firstKey: string, secondKey: string, minDifference: number) {
  return (c: AbstractControl): {[key: string]: any} => {
    if (!c.get(firstKey).value || !c.get(secondKey).value ||
      Math.abs(c.get(firstKey).value - c.get(secondKey).value) >= minDifference) {
      // If there is only one error and it's this one then remove all errors from the control (removing 1 does not work)
      if (c.get(secondKey).hasError('minDifference')) {
        // If previously our error has been set, remove it.
        delete c.get(secondKey).errors.minDifference;
        // If no errors remain after, set the control to be valid.
        if (Object.keys(c.get(secondKey).errors).length === 0) {
          c.get(secondKey).setErrors(null);
        }
      }
      return null;
    }
    // Condition was not met, add our error to the alreadying existing ones.
    c.get(secondKey).setErrors( {...c.get(secondKey).errors, ...{ minDifference: true}} )
  }
}

To be honest, I don't really like my solution, I'd expect to be able to solve this much simpler, but couldn't find a way to do so.

Comments

2

If you are setting the erro manually you can use setValue() to turn it valid again.

if(myCurrency is smallerThanOther){
 this.currencyForm.controls['currencyMaxSell'].setErrors({smallerThan: true})
} else {
 this.currencyForm.controls['currencyMaxSell'].setValue(myCurrency);
}

1 Comment

It's not working for me, the error stays event after setting the value.
2

To clear error on a single form control

this.myFormGroup.get('myControl').reset() 

To clear errors on all form controls

this.myFormGroup.reset() 

Note: this will also reset your controls. So you may use with

this.myFormGroup.get('myControl').setValue(myValue) 

to set the value to whatever you want, but without the errors.

1 Comment

To clear up this.myFormGroup.reset() only resets the value of the control. It does not clear the validation errors or set the control to its initial pristine or untouched state. If you want to reset the control's validation state, you can call the setErrors(null) method on the control to clear any validation errors.
2

To remove an error from the ValidatioErrors object there are some options:

1) Clear them all

This remove ALL errors from the element. setErrors will update the validity of the controls state so you don't have to (most of the time).

WARNING: You need to pass null as calling this without a value causes undesirable results.

Also, if this control had other validation errors on it, you just removed them as well.

  mycontrol.setErrors(null);

2) Set it to null

Setting the error to null is an option. However, when you inspect mycontrol.errors the error will still be present. This can cause side effects if it is not the desired effect.

  mycontrol.setErrors({ myError: null});

3) Remove it completely

This is a bit complicated, but the process is simple. Detect, delete and re-evaluate.

  if (mycontrol.hasError('sharedValue')) {
    delete mycontrol.errors.sharedValue;
    mycontrol.updateValueAndValidity({ onlySelf: true});
  }

Conclusion

Which of these you use really depends on your use case. I prefer the 3rd solution as it makes any of my custom validators that set errors explicitly, instead of implicilty, behave in a very similar manor.

1) Use this when you are certain that your error is the only one ever on the control

2) Use this when you want to modify the error, but set it to be a specific value

3) Use this when you want to remove the error without impacting any other errors that could be on the control when your code executes

Comments

0

You will need a mix of the best answer here and the answer in the comments in order to get your form to remove the error and to become valid for re-submission:

if (this.currencyForm.hasError("smallerThan")) {
 this.currencyForm.setErrors({
  "currencyMaxSell": null
  });
  this.currencyForm.updateValueAndValidity();
}

If the error is on a specific control on the form then include the form control:

if (this.currencyForm.controls.currencyMaxSell.hasError("smallerThan")) {
 this.currencyForm.setErrors({
  "currencyMaxSell": null
  });
  this.currencyForm.updateValueAndValidity();
}

Comments

0

Just try this:

const value = this.currencyForm.controls['currencyMaxSell'].value;
this.currencyForm.controls['currencyMaxSell'].patchValue();
this.currencyForm.controls['currencyMaxSell'].patchValue(value);

You have to actually change the value once, so the fromControl would recheck whether it is valid or not.

Comments

0

In addition to what @karoluS has suggested, you can simply use:

delete control.errors.errorName;

So in your case:

delete this.currencyForm.controls['currencyMaxSell'].errors.smallerThan;

Comments

0

this function adds and removes single error

    manageErrors(whatToDo: 'add' | 'remove', control: AbstractControl, err: string) {

        const errors = control.errors; // get control errors

        if (whatToDo === 'add') { // add errors

          // add your new error
          if (errors) {
            errors[err] = true;
            control.setErrors(errors);
          } else {
            control.setErrors({ [err]: true });
          }

        } else if (whatToDo === 'remove') { // remove errors

          if (errors) {
            // delete your error
            delete errors[err];

            // If any errors are left
            if (Object.keys(errors).length) {
              control.setErrors(errors); // controls got other errors so set them back
            } else {
              control.setErrors(null); // set control errors to null (making it VALID)
            }
          }
        }
      }

Comments

-1

Use can use this below mention method. this will set or remove error in particular control.

errorInFields(control: AbstractControl,key,value){
let errors  = control.errors;
if(!errors){
  if(value == null){
    control.setErrors(null);
  }else{
    let error = {};
    error[key] = value;
    control.setErrors(error);
  }
}else{

  if(value == null){
    if(errors.hasOwnProperty(key)){
      delete errors[key];
    }
    let errorsKey = Object.getOwnPropertyNames(errors);;
    if(errorsKey.length <= 0){
      control.setErrors(null);
    }else{
      control.setErrors(errors);
    }
  }else{
    errors[key] = value;
    control.setErrors(errors);
  }
}
}

Comments

-1

As mentioned here discussion. There is currently no "right" way to do this. Because the desired behaviour is not final. But you can use this handy workaround for the problem:

if ( control.hasError('errorToRemove') ) { // this validation is optional, I think
  const { errorToRemove, ...errors } = control.errors;
  control.setErrors(errors);
  control.updateValueAndValidity();
}

credits Jose Salazar

Comments

-5

To remove only one form control error use .setErrors() with element.

this.myFormGroup.get('myControl').setErrors(
)

This will remove only one element error.

1 Comment

The setErrors() function doesn't accept a call without any parameters. To reset the errors you have to pass null : setErrors(null). Apply to Angular v6

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.